28 #ifndef _mpqc_src_lib_util_misc_consumableresources_h
29 #define _mpqc_src_lib_util_misc_consumableresources_h
35 #include <mpqc_config.h>
36 #include <util/keyval/keyval.h>
37 #include <util/state/statein.h>
38 #include <util/state/stateout.h>
39 #include <util/misc/scexception.h>
40 #include <util/group/thread.h>
41 #include <util/misc/bug.h>
71 size_t max_disk()
const;
83 void consume_disk(
size_t value);
89 void release_disk(
size_t value);
110 bool print_state =
true,
111 bool print_stats =
false)
const;
113 std::string
sprint()
const;
116 template <
typename T> T*
allocate(std::size_t size) {
117 if (size == 0)
return 0;
123 array = (size > 1) ?
new T[size] :
new T;
125 catch (std::bad_alloc&) {
126 std::ostringstream oss;
127 oss <<
"ConsumableResources::allocate(size=" << size <<
"): allocation failed";
129 throw MemAllocFailed(oss.str().c_str(),__FILE__,__LINE__,size*
sizeof(T));
135 consume_memory_(size);
138 if (size >
sizeof(T))
delete[] array;
144 void* array_ptr = static_cast<void*>(array);
146 ExEnv::out0() << indent <<
"ConsumableResources::allocate(size="
147 << size <<
") => array=" << array_ptr << std::endl;
149 std::map<void*, ResourceAttribites>::iterator pos =
150 managed_arrays_.find(array_ptr);
151 if (pos != managed_arrays_.end()) {
152 ExEnv::out0() << indent <<
"WARNING: " << array_ptr
153 <<
" is on the list of managed buffers. size="
154 << managed_arrays_[array_ptr].size << std::endl;
157 ResourceAttribites attr(size);
158 managed_arrays_[array_ptr] = attr;
164 template <
typename T>
void deallocate(T*
const & array) {
167 if (object_is_gone())
return;
169 if (not do_profile()) {
175 ThreadLockHolder lh(lock_);
176 void* array_ptr = static_cast<void*>(array);
178 std::map<void*, ResourceAttribites>::iterator pos = managed_arrays_.find(array_ptr);
179 if (pos != managed_arrays_.end()) {
180 const size_t size = pos->second.size;
181 if (size >
sizeof(T))
delete[] array;
183 release_memory_(size);
185 ExEnv::out0() << indent <<
"ConsumableResources::deallocate(array=" << array_ptr <<
"): size=" << size << std::endl;
187 managed_arrays_.erase(pos);
190 throw ProgrammingError(
"ConsumableResources::deallocate() -- non-managed array given",
196 if (object_is_gone())
return;
199 deallocate<T>(const_cast<T* const &>(array));
209 template <
typename T>
void manage_array(T*
const & array, std::size_t size) {
210 if (not do_profile())
return;
215 void* array_ptr = static_cast<void*>(array);
217 std::map<void*, ResourceAttribites>::iterator pos = managed_arrays_.find(array_ptr);
218 if (pos != managed_arrays_.end()) {
219 std::ostringstream oss;
220 oss << indent <<
"ConsumableResources::manage_array() -- given managed array (ptr="
221 << array_ptr <<
" size=" << size <<
")";
226 consume_memory_(size);
233 ResourceAttribites attr(size);
234 managed_arrays_[array_ptr] = attr;
236 ExEnv::out0() << indent <<
"ConsumableResources::manage_array(array=" << array_ptr <<
", size=" << size <<
")" << std::endl;
242 if (object_is_gone())
return;
243 if (not do_profile())
return;
247 void* array_ptr = static_cast<void*>(array);
249 std::map<void*, ResourceAttribites>::iterator pos = managed_arrays_.find(array_ptr);
250 if (pos != managed_arrays_.end()) {
251 const size_t size = pos->second.size;
252 release_memory_(size);
254 ExEnv::out0() << indent <<
"ConsumableResources::unmanage_array(array=" << array_ptr <<
": size=" << size <<
")" << std::endl;
256 managed_arrays_.erase(pos);
259 void* array_ptr = static_cast<void*>(array);
260 std::ostringstream oss;
261 oss <<
"ConsumableResources::unmanage_array() -- given non-managed array (ptr="
262 << array_ptr <<
" size=" << pos->second.size <<
")";
269 static bool debug() {
return MPQC_MEMORY_CHECK >= 3; }
271 static bool do_profile() {
return MPQC_MEMORY_CHECK >= 1; }
274 static ClassDesc class_desc_;
277 void consume_memory_(
size_t value);
279 void consume_disk_(
size_t value);
283 void release_memory_(
size_t value);
285 void release_disk_(
size_t value);
289 bool object_is_gone();
291 static bool default_object_is_gone();
297 void summarize_unreleased_resources(std::ostream& os =
sc::ExEnv::err0())
const;
301 static std::pair<std::string,size_t> disk;
304 template <
typename T>
class ResourceCounter {
312 ResourceCounter(
const T& max_value) :
313 max_value_(max_value),
315 lowest_value_(max_value)
318 ResourceCounter(
const T& max_value,
const T& value) :
319 max_value_(max_value),
323 MPQC_ASSERT(value <= max_value);
325 ResourceCounter(
const ResourceCounter&
other) :
326 max_value_(
other.max_value_),
327 value_(
other.value_),
328 lowest_value_(
other.lowest_value_)
331 ResourceCounter& operator=(
const ResourceCounter&
other) {
332 max_value_ =
other.max_value_;
333 value_ =
other.value_;
334 lowest_value_ =
other.lowest_value_;
337 operator T()
const {
return value_; }
338 ResourceCounter& operator+=(
const T& val) { value_ = std::min(max_value_, value_ + val);
return *
this; }
340 ResourceCounter& operator-=(
const T& val) {
341 value_ = std::max(T(0), value_ - val);
342 lowest_value_ = std::min(value_,lowest_value_);
346 const T& max_value()
const {
return max_value_; }
347 const T& value()
const {
return value_; }
348 const T& lowest_value()
const {
return lowest_value_; }
350 static std::string value_to_string(T value) {
351 return to_string(value,
true);
353 static std::string difference_to_string(T value) {
354 return to_string(value,
false);
360 s.get(lowest_value_);
365 s.put(lowest_value_);
373 static std::string to_string(T t,
bool may_be_unlimited) {
376 if (may_be_unlimited && t == std::numeric_limits<T>::max())
381 double thousand_m = 1;
382 double thousand_mp1 = 1000;
383 while (t >= thousand_mp1) {
385 thousand_m = thousand_mp1;
386 thousand_mp1 *= 1000;
392 case 0: unit =
"B";
break;
393 case 1: unit =
"kB";
break;
394 case 2: unit =
"MB";
break;
395 case 3: unit =
"GB";
break;
396 case 4: unit =
"TB";
break;
397 case 5: unit =
"PB";
break;
398 case 6: unit =
"EB";
break;
399 case 7: unit =
"ZB";
break;
400 case 8: unit =
"YB";
break;
401 default: MPQC_ASSERT(
false);
break;
405 std::ostringstream oss;
407 oss << (double)t/(
double)thousand_m << unit;
412 typedef ResourceCounter<size_t> rsize;
414 std::pair<std::string, rsize> disk_;
417 struct ResourceAttribites {
418 ResourceAttribites() : size(0) {
420 ResourceAttribites(std::size_t s) : size(s) {
423 #if MPQC_MEMORY_CHECK >= 2
424 Debugger::Backtrace backtrace;
426 operator std::string()
const {
427 std::ostringstream oss;
428 oss <<
"size=" << size;
429 #if MPQC_MEMORY_CHECK >= 2
430 const size_t nframes_to_skip = 1;
431 oss <<
" allocated at:" << std::endl << backtrace.str(nframes_to_skip);
439 std::map<void*, ResourceAttribites> managed_arrays_;
440 Ref<ThreadLock> lock_;
442 static Ref<ConsumableResources> default_instance_;
447 template <
typename T> T*
allocate(std::size_t size) {
456 template <
typename T>
void deallocate(T*
const & array) {
463 template <
typename T>
void manage_array(T*
const & array, std::size_t size) {
467 template <
typename T>
void unmanage_array(T*
const & array) {
474 #endif // end of header guard