メインページ | モジュール | 名前空間一覧 | クラス階層 | 構成 | ファイル一覧 | 名前空間メンバ | 構成メンバ | ファイルメンバ | 関連ページ

toppers/allocator.hpp

解説を見る。
00001 /*
00002  *  TOPPERS/C++ API Template Library
00003  *      Toyohashi Open Platform for Embedded Real-Time Systems/
00004  *      C++ API Template Library
00005  *
00006  *  Copyright (C) 2004 by TAKAGI Nobuhisa
00007  *
00008  *  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation
00009  *  によって公表されている GNU General Public License の Version 2 に記
00010  *  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
00011  *  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
00012  *  利用と呼ぶ)することを無償で許諾する.
00013  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
00014  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
00015  *      スコード中に含まれていること.
00016  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
00017  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
00018  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
00019  *      の無保証規定を掲載すること.
00020  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
00021  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
00022  *      と.
00023  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
00024  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
00025  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
00026  *        報告すること.
00027  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
00028  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
00029  *
00030  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
00031  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
00032  *  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
00033  *  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
00034  *
00035  *  @(#) $Id: allocator.hpp,v 1.3 2004/04/19 01:36:10 takagi-n Exp $
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             // 静的データメンバにするとVisual C++.net 2003でコンパイルできなくなる。
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_