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
22using namespace basis;
23
24namespace structures {
25
26#undef LOG
27#define LOG(to_print) printf("%s\n", astring(to_print).s())
28
29class ml_memory_record
30{
31public:
32 int _usage;
33
34 ml_memory_record(int initial) : _usage(initial) {}
35};
36
38
39class ml_memory_state_meter : public int_hash<ml_memory_record>
40{
41public:
42 ml_memory_state_meter() : int_hash<ml_memory_record>(10) {}
43};
44
46
47memory_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
69ml_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
77int 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
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()?
97 : "unlimited";
98 astring avail = overall_limit()?
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()?
110 : "unlimited";
111 astring avail = individual_limit()?
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
127bool 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
153bool 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
#define LOG(s)
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
int_hash(int estimated_elements)
Definition int_hash.h:72
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".
memory_limiter(int overall_limit, int individual_limit)
creates a limiter that allows "overall_limit" bytes to be in use.
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:54
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.
A dynamic container class that holds any kind of object via pointers.
Definition amorph.h:55