feisty meow concerns codebase  2.140
memory_limiter.cpp
Go to the documentation of this file.
1 /*****************************************************************************\
2 * *
3 * Name : memory_limiter *
4 * Author : Chris Koeritz *
5 * *
6 *******************************************************************************
7 * Copyright (c) 2001-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
14 
15 #include "int_hash.h"
16 #include "memory_limiter.h"
17 
18 #include <basis/functions.h>
19 
20 #include <stdio.h>
21 
22 using namespace basis;
23 
24 namespace structures {
25 
26 #undef LOG
27 #define LOG(to_print) printf("%s\n", astring(to_print).s())
28 
29 class ml_memory_record
30 {
31 public:
32  int _usage;
33 
34  ml_memory_record(int initial) : _usage(initial) {}
35 };
36 
38 
39 class ml_memory_state_meter : public int_hash<ml_memory_record>
40 {
41 public:
42  ml_memory_state_meter() : int_hash<ml_memory_record>(10) {}
43 };
44 
46 
47 memory_limiter::memory_limiter(int overall_limit, int individual_limit)
48 : _overall_limit(overall_limit),
49  _individual_limit(individual_limit),
50  _overall_size(0),
51  _individual_sizes(new ml_memory_state_meter)
52 {
53 }
54 
56 {
57  WHACK(_individual_sizes);
58 }
59 
61 {
62  _overall_size = 0;
63  _individual_sizes->reset();
64 }
65 
67 { return _individual_sizes->ids(); }
68 
69 ml_memory_record *memory_limiter::find_individual(int individual) const
70 {
71  ml_memory_record *to_return = NULL_POINTER;
72  if (!_individual_sizes->find(individual, to_return)) return NULL_POINTER;
73  // no record for that guy.
74  return to_return;
75 }
76 
77 int memory_limiter::individual_usage(int individual) const
78 {
79  ml_memory_record *found = find_individual(individual);
80  if (!found) return 0;
81  return found->_usage;
82 }
83 
84 int memory_limiter::individual_space_left(int individual) const
85 {
86  if (!individual_limit()) return 0;
87  return individual_limit() - individual_usage(individual);
88 }
89 
91 {
92  astring to_return;
93  astring indentat(' ', indent);
94 
95  astring allowed = overall_limit()?
96  astring(astring::SPRINTF, "%dK", overall_limit() / KILOBYTE)
97  : "unlimited";
98  astring avail = overall_limit()?
99  astring(astring::SPRINTF, "%dK", overall_space_left() / KILOBYTE)
100  : "unlimited";
101 
102  to_return += astring(astring::SPRINTF, "Overall Limit=%s, Allocations=%dK, "
103  "Free Space=%s", allowed.s(), overall_usage() / KILOBYTE, avail.s());
104  to_return += "\n";
105 
106  int_set individuals = _individual_sizes->ids();
107  for (int i = 0; i < individuals.elements(); i++) {
108  astring allowed = individual_limit()?
109  astring(astring::SPRINTF, "%dK", individual_limit() / KILOBYTE)
110  : "unlimited";
111  astring avail = individual_limit()?
112  astring(astring::SPRINTF, "%dK",
113  individual_space_left(individuals[i]) / KILOBYTE) : "unlimited";
114 
115  to_return += indentat + astring(astring::SPRINTF, "individual %d: "
116  "Limit=%s, Used=%dK, Free=%s", individuals[i], allowed.s(),
117  individual_usage(individuals[i]) / KILOBYTE, avail.s());
118  to_return += "\n";
119  }
120  if (!individuals.elements()) {
121  to_return += indentat + "No allocations owned currently.";
122  to_return += "\n";
123  }
124  return to_return;
125 }
126 
127 bool memory_limiter::okay_allocation(int individual, int memory_desired)
128 {
129  FUNCDEF("okay_allocation");
130  // check the overall allocation limits first.
131  if (_overall_limit
132  && (_overall_size + memory_desired > _overall_limit) ) return false;
133  // now check sanity of this request.
134  if (_individual_limit && (memory_desired > _individual_limit) ) return false;
135  // now check the allocations per user.
136  ml_memory_record *found = find_individual(individual);
137  if (!found) {
138  _individual_sizes->add(individual, new ml_memory_record(0));
139  found = find_individual(individual);
140  if (!found) {
141  LOG("ERROR: adding a new record to the memory state!");
142  return false;
143  }
144  }
145  if (_individual_limit
146  && (found->_usage + memory_desired > _individual_limit) )
147  return false;
148  found->_usage += memory_desired;
149  _overall_size += memory_desired;
150  return true;
151 }
152 
153 bool memory_limiter::record_deletion(int individual, int memory_deleted)
154 {
155  if (memory_deleted < 0) return false; // bogus.
156  // make sure the individual exists.
157  ml_memory_record *found = find_individual(individual);
158  if (!found) return false;
159  // the individual must have actually allocated at least that much previously.
160  if (found->_usage < memory_deleted) return false;
161  // okay, we think that's reasonable.
162  found->_usage -= memory_deleted;
163  _overall_size -= memory_deleted;
164  // clean out an empty locker.
165  if (!found->_usage) _individual_sizes->zap(individual);
166  return true;
167 }
168 
169 } //namespace.
170 
171 
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
const char * s() const
synonym for observe. the 's' stands for "string", if that helps.
Definition: astring.h:113
A simple object that wraps a templated set of ints.
Definition: set.h:156
int individual_usage(int individual) const
returns the amount of memory used by "individual".
int overall_space_left() const
returns the overall space left for allocation.
int overall_limit() const
returns the current overall limit.
bool okay_allocation(int individual, int memory_desired)
returns true if "individual" may allocate "memory_desired" bytes.
bool record_deletion(int individual, int memory_deleted)
acknowledges that the "individual" freed "memory_deleted" bytes.
int overall_usage() const
returns the size used by all managed memory.
int individual_limit() const
returns the current individual limit.
const structures::int_set & individuals_listed() const
reports the current set of individuals using memory.
basis::astring text_form(int indent=0) const
returns a string that lists out the overall plus individual limits.
int individual_space_left(int individual) const
returns the space left for the individual specified.
void reset()
returns the object to a pristine state.
int elements() const
Returns the number of elements in this set.
Definition: set.h:47
#define NULL_POINTER
The value representing a pointer to nothing.
Definition: definitions.h:32
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:57
#define LOG(to_print)
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
Definition: functions.h:121
const int KILOBYTE
Number of bytes in a kilobyte.
Definition: definitions.h:134
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55