00001 #ifndef MEMORY_LIMITER_IMPLEMENTATION_FILE
00002 #define MEMORY_LIMITER_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "int_hash.cpp"
00019 #include "memory_limiter.h"
00020
00021 #include <basis/function.h>
00022 #include <basis/log_base.h>
00023
00024 #undef LOG
00025 #define LOG(to_print) CLASS_EMERGENCY_LOG(program_wide_logger(), to_print)
00026
00027 class ml_memory_record
00028 {
00029 public:
00030 int _usage;
00031
00032 ml_memory_record(int initial) : _usage(initial) {}
00033 };
00034
00036
00037 class ml_memory_state_meter : public int_hash<ml_memory_record>
00038 {
00039 public:
00040 ml_memory_state_meter() : int_hash<ml_memory_record>(10) {}
00041 };
00042
00044
00045 memory_limiter::memory_limiter(int overall_limit, int individual_limit)
00046 : _overall_limit(overall_limit),
00047 _individual_limit(individual_limit),
00048 _overall_size(0),
00049 _individual_sizes(new ml_memory_state_meter)
00050 {
00051 }
00052
00053 memory_limiter::~memory_limiter()
00054 {
00055 WHACK(_individual_sizes);
00056 }
00057
00058 void memory_limiter::reset()
00059 {
00060 _overall_size = 0;
00061 _individual_sizes->reset();
00062 }
00063
00064 const int_set &memory_limiter::individuals_listed() const
00065 { return _individual_sizes->ids(); }
00066
00067 ml_memory_record *memory_limiter::find_individual(int individual) const
00068 {
00069 ml_memory_record *to_return = NIL;
00070 if (!_individual_sizes->find(individual, to_return)) return NIL;
00071
00072 return to_return;
00073 }
00074
00075 int memory_limiter::individual_usage(int individual) const
00076 {
00077 ml_memory_record *found = find_individual(individual);
00078 if (!found) return 0;
00079 return found->_usage;
00080 }
00081
00082 int memory_limiter::individual_space_left(int individual) const
00083 {
00084 if (!individual_limit()) return 0;
00085 return individual_limit() - individual_usage(individual);
00086 }
00087
00088 istring memory_limiter::text_form(int indent) const
00089 {
00090 istring to_return;
00091 istring indentat(' ', indent);
00092
00093 istring allowed = overall_limit()?
00094 istring(istring::SPRINTF, "%dK", overall_limit() / KILOBYTE)
00095 : "unlimited";
00096 istring avail = overall_limit()?
00097 istring(istring::SPRINTF, "%dK", overall_space_left() / KILOBYTE)
00098 : "unlimited";
00099
00100 to_return += istring(istring::SPRINTF, "Overall Limit=%s, Allocations=%dK, "
00101 "Free Space=%s", allowed.s(), overall_usage() / KILOBYTE, avail.s());
00102 to_return += log_base::platform_ending();
00103
00104 int_set individuals = _individual_sizes->ids();
00105 for (int i = 0; i < individuals.elements(); i++) {
00106 istring allowed = individual_limit()?
00107 istring(istring::SPRINTF, "%dK", individual_limit() / KILOBYTE)
00108 : "unlimited";
00109 istring avail = individual_limit()?
00110 istring(istring::SPRINTF, "%dK",
00111 individual_space_left(individuals[i]) / KILOBYTE) : "unlimited";
00112
00113 to_return += indentat + istring(istring::SPRINTF, "individual %d: "
00114 "Limit=%s, Used=%dK, Free=%s", individuals[i], allowed.s(),
00115 individual_usage(individuals[i]) / KILOBYTE, avail.s());
00116 to_return += log_base::platform_ending();
00117 }
00118 if (!individuals.elements()) {
00119 to_return += indentat + "No allocations owned currently.";
00120 to_return += log_base::platform_ending();
00121 }
00122 return to_return;
00123 }
00124
00125 bool memory_limiter::okay_allocation(int individual, int memory_desired)
00126 {
00127 FUNCDEF("okay_allocation");
00128
00129 if (_overall_limit
00130 && (_overall_size + memory_desired > _overall_limit) ) return false;
00131
00132 if (_individual_limit && (memory_desired > _individual_limit) ) return false;
00133
00134 ml_memory_record *found = find_individual(individual);
00135 if (!found) {
00136 _individual_sizes->add(individual, new ml_memory_record(0));
00137 found = find_individual(individual);
00138 if (!found) {
00139 LOG("ERROR: adding a new record to the memory state!");
00140 return false;
00141 }
00142 }
00143 if (_individual_limit
00144 && (found->_usage + memory_desired > _individual_limit) )
00145 return false;
00146 found->_usage += memory_desired;
00147 _overall_size += memory_desired;
00148 return true;
00149 }
00150
00151 bool memory_limiter::record_deletion(int individual, int memory_deleted)
00152 {
00153 if (memory_deleted < 0) return false;
00154
00155 ml_memory_record *found = find_individual(individual);
00156 if (!found) return false;
00157
00158 if (found->_usage < memory_deleted) return false;
00159
00160 found->_usage -= memory_deleted;
00161 _overall_size -= memory_deleted;
00162
00163 if (!found->_usage) _individual_sizes->zap(individual);
00164 return true;
00165 }
00166
00167
00168 #endif //MEMORY_LIMITER_IMPLEMENTATION_FILE
00169