25 #ifndef __TPIE_MEMORY_H__
26 #define __TPIE_MEMORY_H__
28 #include <tpie/config.h>
30 #include <boost/thread/mutex.hpp>
31 #include <boost/unordered_map.hpp>
32 #include <boost/type_traits/is_polymorphic.hpp>
51 virtual const char* what()
const throw() {
return msg;}
79 size_t used()
const throw();
89 inline
size_t limit() const throw() {
return m_limit;}
139 void register_pointer(
void * p,
size_t size,
const std::type_info & t);
140 void unregister_pointer(
void * p,
size_t size,
const std::type_info & t);
141 void assert_tpie_ptr(
void * p);
142 void complain_about_unfreed_memory();
147 std::auto_ptr<bits::atomic_int> m_used;
149 size_t m_maxExceeded;
150 size_t m_nextWarning;
154 boost::mutex m_mutex;
157 void __register_pointer(
void * p,
size_t size,
const std::type_info & t);
158 void __unregister_pointer(
void * p,
size_t size,
const std::type_info & t);
159 void __assert_tpie_ptr(
void * p);
160 void __complain_about_unfreed_memory();
162 boost::unordered_map<void *, std::pair<size_t, const std::type_info *> > m_pointers;
225 template <typename T, bool x=boost::is_polymorphic<T>::value >
229 struct __object_addr {
230 inline void * operator()(T * o) {
return static_cast<void *
>(o);}
236 template <
typename T>
237 struct __object_addr<T, true> {
238 inline void * operator()(T * o) {
return dynamic_cast<void *
>(o);}
249 template <
typename D,
typename T>
250 inline D
ptr_cast(T * t) {
return reinterpret_cast<D
>(__object_addr<T>()(t)); }
253 template <
typename T>
254 inline T * __allocate() {
255 if(!boost::is_polymorphic<T>::value)
return reinterpret_cast<T *
>(
new uint8_t[
sizeof(T)]);
256 uint8_t * x =
new uint8_t[
sizeof(T)+
sizeof(
size_t)];
257 *
reinterpret_cast<size_t*
>(x) =
sizeof(T);
258 return reinterpret_cast<T*
>(x +
sizeof(size_t));
261 template <
typename T>
262 inline size_t tpie_size(T * p) {
263 if(!boost::is_polymorphic<T>::value)
return sizeof(T);
264 uint8_t * x =
ptr_cast<uint8_t *>(p);
265 return *
reinterpret_cast<size_t *
>(x -
sizeof(size_t));
273 template <
typename T>
282 inline T * allocate() {
304 template <
typename T>
310 inline T * allocate() {
312 deregister =
sizeof(T);
313 data = __allocate<T>();
327 delete[]
reinterpret_cast<uint8_t*
>(data);
337 template <
typename T>
346 template <
typename T,
typename Args>
362 #elif defined(TPIE_CPP_VARIADIC_TEMPLATES) && defined(TPIE_CPP_RVALUE_REFERENCE)
364 template <
typename T,
typename ... Args>
365 inline T *
tpie_new(Args &&... args) {
366 allocation_scope_magic<T> m;
367 new(m.allocate()) T(std::forward<Args>(args)...);
372 #include <tpie/memory.inl>
379 template <
typename T>
383 uint8_t * pp =
ptr_cast<uint8_t *>(p);
386 if(!boost::is_polymorphic<T>::value)
389 delete[] (pp -
sizeof(size_t));
397 template <
typename T>
405 template <
typename T>
408 explicit inline auto_ptr_ref(T * ptr)
throw(): m_ptr(ptr) {};
415 template <
typename T>
422 typedef T element_type;
425 explicit inline auto_ptr(T * o=0)
throw(): elm(0){reset(o);}
430 inline auto_ptr & operator =(
auto_ptr & o)
throw() {reset(o.release());
return *
this;}
435 inline ~
auto_ptr()
throw() {reset();}
438 inline T & operator*()
const throw() {
return *elm;}
439 inline T * operator->()
const throw() {
return elm;}
440 inline T *
get()
const throw() {
return elm;}
441 inline T * release()
throw () {T * t=elm; elm=0;
return t;}
442 inline void reset(T * o=0)
throw () {
443 if (o == elm)
return;
467 typedef std::allocator<T> a_t;
470 typedef typename a_t::size_type size_type;
471 typedef typename a_t::difference_type difference_type;
472 typedef typename a_t::pointer pointer;
473 typedef typename a_t::const_pointer const_pointer;
474 typedef typename a_t::reference reference;
475 typedef typename a_t::const_reference const_reference;
476 typedef typename a_t::value_type value_type;
480 template <
typename T2>
485 inline T * allocate(
size_t size,
const void * hint=0) {
487 T * res = a.allocate(size, hint);
492 inline void deallocate(T * p,
size_t n) {
496 return a.deallocate(p, n);
498 inline size_t max_size()
const {
return a.max_size();}
500 #ifdef TPIE_CPP_RVALUE_REFERENCE
501 #ifdef TPIE_CPP_VARIADIC_TEMPLATES
502 template <
typename ...TT>
503 inline void construct(T * p, TT &&...x) {a.construct(p, x...);}
507 #pragma clang diagnostic push
509 #pragma clang diagnostic ignored "-Wc++11-extensions"
511 template <
typename TT>
512 inline void construct(T * p, TT && val) {a.construct(p, val);}
515 #pragma clang diagnostic pop
519 inline void construct(T * p) {
521 #pragma warning( push )
522 #pragma warning(disable: 4345)
526 #pragma warning( pop )
529 inline void construct(T * p,
const T& val) {a.construct(p, val);}
530 inline void destroy(T * p) {a.destroy(p);}
531 inline pointer address(reference x)
const {
return &x;}
532 inline const_pointer address(const_reference x)
const {
return &x;}
535 template <
typename T>
551 template <
typename T>
554 a.reset(b.release());
559 #endif //__TPIE_MEMORY_H__
size_t limit() const
Return the memory limit.
size_t consecutive_memory_available(size_t granularity=5 *1024 *1024)
Find the largest amount of memory that can be allocated as a single chunk.
enforce_t
Memory limit enforcement policies.
void __register_pointer(void *p, size_t size, const std::type_info &t)
Ignore when running out of memory.
Throw an out_of_memory_error when the memory limit is exceeded.
void unused(const T &x)
Declare that a variable is unused on purpose.
Log to debug log when the memory limit is exceeded.
void __unregister_pointer(void *p, size_t size, const std::type_info &t)
size_t available() const
Return the amount of memory still available to allocation.
enforce_t enforcement()
Return the current memory limit enforcement policy.
T * tpie_new_array(size_t size)
Allocate a new array and register its memory usage.
void register_deallocation(size_t bytes)
A allocator object usable in STL containers, using the TPIE memory manager.
memory_manager & get_memory_manager()
Return a reference to the memory manager.
Miscellaneous utility functions.
void finish_memory_manager()
Used by tpie_finish to deinitialize the memory manager.
Log a warning when the memory limit is exceeded.
Memory management object used to track memory usage.
size_t used() const
Return the current amount of memory used.
void tpie_delete(T *p)
Delete an object allocated with tpie_new.
like std::auto_ptr, but delete the object with tpie_delete.
void register_allocation(size_t bytes)
void assert_tpie_ptr(void *p)
In a debug build, assert that a given pointer has been allocated with tpie_new.
std::pair< uint8_t *, size_t > __allocate_consecutive(size_t upper_bound, size_t granularity)
Thrown when trying to allocate too much memory.
void init_memory_manager()
Used by tpie_init to initialize the memory manager.
void set_limit(size_t new_limit)
Update the memory limit.
T * tpie_new(Args args)
Allocate an element of the type given as template parameter, and register its memory usage with TPIE...
void set_enforcement(enforce_t e)
Set the memory limit enforcement policy.
void tpie_delete_array(T *a, size_t size)
Delete an array allocated with tpie_new_array.
D ptr_cast(T *t)
Cast between pointer types.