00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00055 #ifndef TOPPERS_ALLOCATOR_HPP_
00056 #define TOPPERS_ALLOCATOR_HPP_
00057
00058 #include <toppers/fmempool.hpp>
00059 #include <toppers/vmempool.hpp>
00060 #include <toppers/sync.hpp>
00061 #include <new>
00062 #include <cstddef>
00063
00064 namespace toppers
00065 {
00066
00067 template <typename T>
00068 class alignof
00069 {
00070 struct _
00071 {
00072 char a_;
00073 T b_;
00074 };
00075
00076 public:
00077 static const std::size_t value = offsetof(_, b_);
00078 };
00079
00080 namespace detail
00081 {
00082
00083 union max_alignment_helper
00084 {
00085 long l;
00086 #ifdef TOPPERS_LONG_LONG
00087 TOPPERS_LONG_LONG ll;
00088 #endif
00089 double d;
00090 long double ld;
00091 };
00092
00093 }
00094
00095 const std::size_t max_alignment = alignof<detail::max_alignment_helper>::value;
00096
00097 template <typename T>
00098 class rounded_sizeof
00099 {
00100 public:
00101 static const std::size_t value = (sizeof(T) + max_alignment - 1) / max_alignment * max_alignment;
00102 };
00103
00104 inline void throw_bad_alloc()
00105 {
00106 static std::bad_alloc x;
00107 throw x;
00108 }
00109
00120 template <typename T, class Pool>
00121 class allocator
00122 {
00123 Pool pool_;
00124
00125 public:
00127 typedef std::size_t size_type;
00129 typedef std::ptrdiff_t different_type;
00131 typedef T* pointer;
00133 typedef const T* const_pointer;
00135 typedef T& reference;
00137 typedef const T& const_reference;
00139 typedef T value_type;
00140
00142 template <typename T1>
00143 struct rebind
00144 {
00145 typedef allocator<T1, Pool> other;
00146 };
00147
00149 allocator() throw() {}
00151 explicit allocator(const Pool& pool) throw() : pool_(pool) {}
00153 allocator(const allocator&) throw() {}
00155 template <typename T1>
00156 allocator(const allocator<T1, Pool>&) throw() {}
00158 ~allocator() throw() {}
00159
00161 pointer address(reference x) const { return &x; }
00163 const_pointer address(const_reference x) const { return &x; }
00164
00166 T* allocate(size_type n, const void* = 0)
00167 {
00168 if (n > 0)
00169 {
00170 void* p;
00171 if (pool_.get(n * sizeof(T), &p) == E_OK)
00172 return static_cast<T*>(p);
00173 throw_bad_alloc();
00174 }
00175 return 0;
00176 }
00178 void deallocate(pointer p, size_type)
00179 {
00180 pool_.release(p);
00181 }
00182
00184 size_type max_size() const throw()
00185 {
00186 return ~size_type(0) / sizeof(T);
00187 }
00188
00190 void construct(pointer p, const T& value)
00191 {
00192 new(p) T(value);
00193 }
00195 void destroy(pointer p)
00196 {
00197 p->~T();
00198 }
00199 };
00200
00211 template <std::size_t Size, class Pool>
00212 class fixed_sized_allocator
00213 {
00214 void (*handler_)();
00215 Pool pool_;
00216
00217 public:
00218 explicit fixed_sized_allocator(std::new_handler handler = 0) : handler_(handler) {}
00219
00221 template <typename Sync>
00222 void* allocate(Sync sync)
00223 {
00224 void* p;
00225 while (pool_.get(Size, &p, sync) != E_OK)
00226 {
00227 if (handler_ == 0)
00228 throw_bad_alloc();
00229 (*handler_)();
00230 }
00231 return p;
00232 }
00234 void* allocate()
00235 {
00236 return allocate(forever);
00237 }
00239 void deallocate(void* p) throw()
00240 {
00241 pool_.release(p);
00242 }
00244 std::new_handler set_new_handler(std::new_handler handler)
00245 {
00246 std::new_handler prev = handler_;
00247 handler_ = handler;
00248 return prev;
00249 }
00250 };
00251
00266 template <class Host, class Pool, template <std::size_t, class> class Allocator = fixed_sized_allocator>
00267 class fixed_sized_new
00268 {
00269 protected:
00271
00275 ~fixed_sized_new() {}
00276
00277 public:
00279 static void* operator new(std::size_t size) throw(std::bad_alloc)
00280 {
00281 TOPPERS_ASSERT(size <= rounded_sizeof<Host>::value);
00282 return allocator<rounded_sizeof<Host>::value>::get().allocate();
00283 }
00285 static void operator delete(void* p) throw()
00286 {
00287 allocator<rounded_sizeof<Host>::value>::get().deallocate(p);
00288 }
00289
00291
00294 template <typename Sync>
00295 static void* operator new(std::size_t size, Sync sync) throw(std::bad_alloc)
00296 {
00297 TOPPERS_ASSERT(size <= rounded_sizeof<Host>::value);
00298 return allocator<rounded_sizeof<Host>::value>::get().allocate(sync);
00299 }
00301 template <typename Sync>
00302 static void operator delete(void* p, Sync) throw()
00303 {
00304 allocator<rounded_sizeof<Host>::value>::get().deallocate(p);
00305 }
00306
00308 static void* operator new(std::size_t size, const std::nothrow_t& nt) throw()
00309 {
00310 return operator new(size, nt, forever);
00311 }
00313 static void operator delete(void* p, const std::nothrow_t&) throw()
00314 {
00315 operator delete(p);
00316 }
00317
00319 template <typename Sync>
00320 static void* operator new(std::size_t size, const std::nothrow_t&, Sync sync) throw()
00321 {
00322 void* p = 0;
00323 try
00324 {
00325 TOPPERS_ASSERT(size <= rounded_sizeof<Host>::value);
00326 p = allocator<rounded_sizeof<Host>::value>::get().allocate(sync);
00327 }
00328 catch (...)
00329 {
00330 }
00331 return p;
00332 }
00334 template <typename Sync>
00335 static void operator delete(void* p, const std::nothrow_t&, Sync) throw()
00336 {
00337 allocator<rounded_sizeof<Host>::value>::get().deallocate(p);
00338 }
00339
00341 std::new_handler set_new_handler(std::new_handler handler)
00342 {
00343 return allocator<rounded_sizeof<Host>::value>::get().set_new_handler(handler);
00344 }
00345
00346 private:
00347 template <std::size_t Size>
00348 struct allocator
00349 {
00350
00351 static Allocator<Size, Pool>& get()
00352 {
00353 static Allocator<Size, Pool> impl;
00354 return impl;
00355 }
00356 };
00357 };
00358
00370 template <class Host, class Pool>
00371 class variable_sized_new
00372 {
00373 static FP handler_;
00374 static Pool pool_;
00375
00376 protected:
00378
00382 ~variable_sized_new() {}
00383
00384 public:
00386 static void* operator new(std::size_t size) throw(std::bad_alloc)
00387 {
00388 void* p = 0;
00389 while (pool_.get(UINT(size), &p) != E_OK)
00390 {
00391 if (handler_ == 0)
00392 throw_bad_alloc();
00393 (*handler_)();
00394 }
00395 return p;
00396 }
00398 static void operator delete(void* p) throw()
00399 {
00400 pool_.release(p);
00401 }
00402
00408 template <typename Sync>
00409 static void* operator new(std::size_t size, Sync sync) throw(std::bad_alloc)
00410 {
00411 void* p = 0;
00412 while (pool_.get(size, &p, sync) != E_OK)
00413 {
00414 if (handler_ == 0)
00415 throw_bad_alloc();
00416 (*handler_)();
00417 }
00418 return p;
00419 }
00421 template <typename Sync>
00422 static void operator delete(void* p, Sync) throw()
00423 {
00424 pool_.release(p);
00425 }
00426
00428 static void* operator new(std::size_t size, const std::nothrow_t& nt) throw()
00429 {
00430 void* p = 0;
00431 try
00432 {
00433 p = operator new(size);
00434 }
00435 catch (...)
00436 {
00437 }
00438 return p;
00439 }
00441 static void operator delete(void* p, const std::nothrow_t&) throw()
00442 {
00443 operator delete(p);
00444 }
00445
00447 template <typename Sync>
00448 static void* operator new(std::size_t size, const std::nothrow_t&, Sync sync) throw()
00449 {
00450 void* p = 0;
00451 try
00452 {
00453 p = operator new(size, sync);
00454 }
00455 catch (...)
00456 {
00457 }
00458 return p;
00459 }
00461 template <typename Sync>
00462 static void operator delete(void* p, const std::nothrow_t&, Sync sync) throw()
00463 {
00464 operator delete(p, sync);
00465 }
00466
00468 static void* operator new[](std::size_t size) throw(std::bad_alloc)
00469 {
00470 return operator new(size);
00471 }
00473 static void operator delete[](void* p) throw()
00474 {
00475 operator delete(p);
00476 }
00477
00479 template <typename Sync>
00480 static void* operator new[](std::size_t size, Sync sync) throw(std::bad_alloc)
00481 {
00482 return operator new(size, sync);
00483 }
00485 template <typename Sync>
00486 static void operator delete[](void* p, Sync) throw()
00487 {
00488 operator delete(p);
00489 }
00490
00492 static void* operator new[](std::size_t size, const std::nothrow_t& nt) throw()
00493 {
00494 return operator new(size, nt);
00495 }
00497 static void operator delete[](void* p, const std::nothrow_t& nt) throw()
00498 {
00499 operator delete(p, nt);
00500 }
00501
00503 template <typename Sync>
00504 static void* operator new[](std::size_t size, const std::nothrow_t& nt, Sync sync) throw()
00505 {
00506 return operator new(size, nt, sync);
00507 }
00509 template <typename Sync>
00510 static void operator delete[](void* p, const std::nothrow_t& nt, Sync sync) throw()
00511 {
00512 operator delete(p, nt, sync);
00513 }
00514
00516 std::new_handler set_new_handler(std::new_handler handler)
00517 {
00518 std::new_handler prev = handler_;
00519 handler_ = handler;
00520 return prev;
00521 }
00522 };
00523
00524 template <class Host, class Pool>
00525 FP variable_sized_new<Host, Pool>::handler_;
00526
00527 template <class Host, class Pool>
00528 Pool variable_sized_new<Host, Pool>::pool_;
00529
00530
00540 template <std::size_t N = 32, std::size_t Size = 32>
00541 class fixed_simple_pool
00542 {
00543 union node
00544 {
00545 node* next;
00546 char data[Size];
00547 detail::max_alignment_helper force_aligner_;
00548 };
00549 node* top_;
00550 node buf_[N];
00551
00552 public:
00554 fixed_simple_pool() : top_(buf_)
00555 {
00556 node* next = 0;
00557 for (node* cur = &buf_[N - 1]; cur != top_; cur--)
00558 {
00559 cur->next = next;
00560 next = cur;
00561 }
00562 }
00563
00565 ER get(VP* p_blk)
00566 {
00567 node* p = top_;
00568 top_ = p->next;
00569 *p_blk = p;
00570 return E_OK;
00571 }
00572
00574 ER get(VP* p_blk, int sync)
00575 {
00576 return get(p_blk);
00577 }
00578
00580 ER get(UINT size, VP* p_blk)
00581 {
00582 if (size > Size)
00583 return E_PAR;
00584 node* p = top_;
00585 top_ = p->next;
00586 *p_blk = p;
00587 return E_OK;
00588 }
00589
00591 ER get(UINT size, VP* p_blk, int sync)
00592 {
00593 return get(size, p_blk);
00594 }
00595
00597 ER release(VP blk)
00598 {
00599 node* p = static_cast<node*>(blk);
00600 p->next = top_;
00601 top_ = p;
00602 return E_OK;
00603 }
00604 };
00605
00617 template <std::size_t TotalSize = 256>
00618 class variable_simple_pool
00619 {
00620 char* top_;
00621 union
00622 {
00623 char buf_[TotalSize];
00624 detail::max_alignment_helper force_aligner_;
00625 };
00626
00627 public:
00629 variable_simple_pool() : top_(buf_)
00630 {
00631 }
00632
00634 ER get(UINT size, VP* p_blk)
00635 {
00636 typedef detail::max_alignment_helper aligner_type;
00637 size = (size + sizeof(aligner_type) - 1) / sizeof(aligner_type) * sizeof(aligner_type);
00638 if (p_blk == 0)
00639 return E_PAR;
00640 if (top_ + size >= buf_ + TotalSize)
00641 return E_NOMEM;
00642 *p_blk = top_;
00643 top_ += size;
00644 return E_OK;
00645 }
00646
00648 ER get(UINT size, VP* p_blk, int sync)
00649 {
00650 return get(size, p_blk);
00651 }
00652
00654 ER release(VP blk)
00655 {
00656 return E_OK;
00657 }
00658 };
00659
00670 template <std::size_t Size = 32>
00671 class fixed_new_pool
00672 {
00673 public:
00675 ER get(VP* p_blk)
00676 {
00677 if (p_blk == 0)
00678 return E_PAR;
00679 void* p = ::operator new(Size, std::nothrow);
00680 if (p == 0)
00681 return E_NOMEM;
00682 *p_blk = p;
00683 return E_OK;
00684 }
00685
00687 ER get(VP* p_blk, int sync)
00688 {
00689 return get(p_blk);
00690 }
00691
00693 ER get(UINT size, VP* p_blk)
00694 {
00695 if (size > Size)
00696 return E_PAR;
00697 return get(p_blk);
00698 }
00699
00701 ER get(UINT size, VP* p_blk, int sync)
00702 {
00703 return get(size, p_blk);
00704 }
00705
00707 ER release(VP blk)
00708 {
00709 ::operator delete(blk);
00710 return E_OK;
00711 }
00712 };
00713
00724 class variable_new_pool
00725 {
00726 public:
00728 ER get(UINT size, VP* p_blk)
00729 {
00730 if (p_blk == 0)
00731 return E_PAR;
00732 void* p = ::operator new(size);
00733 if (p == 0)
00734 return E_NOMEM;
00735 *p_blk = p;
00736 return E_OK;
00737 }
00738
00740 ER get(UINT size, VP* p_blk, int sync)
00741 {
00742 return get(size, p_blk);
00743 }
00744
00746 ER release(VP blk)
00747 {
00748 ::operator delete(blk);
00749 return E_OK;
00750 }
00751 };
00752
00753 }
00754
00755 #endif // ! TOPPERS_ALLOCATOR_HPP_