ucommon
ucommon/memory.h
Go to the documentation of this file.
00001 // Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
00002 //
00003 // This file is part of GNU uCommon C++.
00004 //
00005 // GNU uCommon C++ is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU Lesser General Public License as published
00007 // by the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // GNU uCommon C++ is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with GNU uCommon C++.  If not, see <http://www.gnu.org/licenses/>.
00017 
00030 #ifndef _UCOMMON_MEMORY_H_
00031 #define _UCOMMON_MEMORY_H_
00032 
00033 #ifndef _UCOMMON_CONFIG_H_
00034 #include <ucommon/platform.h>
00035 #endif
00036 
00037 #ifndef _UCOMMON_PROTOCOLS_H_
00038 #include <ucommon/protocols.h>
00039 #endif
00040 
00041 #ifndef  _UCOMMON_LINKED_H_
00042 #include <ucommon/linked.h>
00043 #endif
00044 
00045 NAMESPACE_UCOMMON
00046 
00047 class PagerPool;
00048 
00056 class __EXPORT memalloc : public MemoryProtocol, protected LockingProtocol
00057 {
00058 private:
00059     friend class bufpager;
00060 
00061     size_t pagesize, align;
00062     unsigned count;
00063 
00064     typedef struct mempage {
00065         struct mempage *next;
00066         union {
00067             void *memalign;
00068             unsigned used;
00069         };
00070     }   page_t;
00071 
00072     page_t *page;
00073 
00074 protected:
00075     unsigned limit;
00076 
00081     page_t *pager(void);
00082 
00083 public:
00088     memalloc(size_t page = 0);
00089 
00093     virtual ~memalloc();
00094 
00099     inline unsigned getPages(void)
00100         {return count;};
00101 
00109     inline unsigned getLimit(void)
00110         {return limit;};
00111 
00116     inline unsigned getAlloc(void)
00117         {return pagesize;};
00118 
00129     unsigned utilization(void);
00130 
00134     void purge(void);
00135 
00143     virtual void *_alloc(size_t size);
00144 };
00145 
00166 class __EXPORT mempager : public memalloc
00167 {
00168 private:
00169     pthread_mutex_t mutex;
00170 
00171 protected:
00178     virtual void _lock(void);
00179 
00183     virtual void _unlock(void);
00184 
00185 public:
00190     mempager(size_t page = 0);
00191 
00195     virtual ~mempager();
00196 
00207     unsigned utilization(void);
00208 
00212     void purge(void);
00213 
00221     virtual void dealloc(void *memory);
00222 
00231     virtual void *_alloc(size_t size);
00232 };
00233 
00239 class __EXPORT stringpager : protected memalloc
00240 {
00241 private:
00242     unsigned members;
00243     LinkedObject *root;
00244 
00245 public:
00252     class __EXPORT member : public LinkedObject
00253     {
00254     private:
00255         const char *text;
00256 
00257     public:
00258         member(LinkedObject **root, const char *data);
00259         inline const char *operator*()
00260             {return text;};
00261 
00262         inline const char *get(void)
00263             {return text;};
00264     };
00265 
00270     stringpager(size_t pagesize = 256);
00271 
00276     inline unsigned count(void)
00277         {return members;};
00278 
00285     const char *get(unsigned item);
00286 
00291     void add(const char *text);
00292 
00298     void add(char **list);
00299 
00304     void clear(void);
00305 
00312     inline const char *operator[](unsigned item)
00313         {return get(item);};
00314 
00320     inline stringpager::member *begin(void)
00321         {return static_cast<stringpager::member *>(root);};
00322 
00327     inline void operator+=(const char *text)
00328         {add(text);};
00329 
00334     inline stringpager& operator<<(const char *text)
00335         {add(text); return *this;};
00336 };
00337 
00342 class __EXPORT bufpager : public memalloc, public CharacterProtocol
00343 {
00344 private:
00345     typedef struct cpage {
00346         struct cpage *next;
00347         char *text;
00348         unsigned size, used;
00349     } cpage_t;
00350 
00351     cpage_t *first, *last, *current, *freelist;
00352     unsigned cpos;
00353     unsigned long ccount;
00354 
00355     virtual int _getch(void);
00356     virtual int _putch(int code);
00357 
00358 protected:
00359     virtual void *_alloc(size_t size);
00360 
00361 public:
00365     void reset(void);
00366 
00370     void rewind(void);
00371 
00376     inline unsigned long getUsed(void)
00377         {return ccount;};
00378 
00379     bufpager(size_t page = 0);
00380 };
00381 
00389 class __EXPORT autorelease
00390 {
00391 private:
00392     LinkedObject *pool;
00393 
00394 public:
00398     autorelease();
00399 
00403     ~autorelease();
00404 
00410     void release(void);
00411 
00416     void operator+=(LinkedObject *object);
00417 };
00418 
00429 class __EXPORT PagerObject : public LinkedObject, public CountedObject
00430 {
00431 protected:
00432     friend class PagerPool;
00433 
00434     PagerPool *pager;
00435 
00439     PagerObject();
00440 
00444     void release(void);
00445 
00449     void dealloc(void);
00450 };
00451 
00460 class __EXPORT PagerPool : public MemoryProtocol
00461 {
00462 private:
00463     LinkedObject *freelist;
00464     pthread_mutex_t mutex;
00465 
00466 protected:
00467     PagerPool();
00468     virtual ~PagerPool();
00469 
00470     PagerObject *get(size_t size);
00471 
00472 public:
00477     void put(PagerObject *object);
00478 };
00479 
00480 class __EXPORT charmem : public CharacterProtocol
00481 {
00482 protected:
00483     char *buffer;
00484     size_t inp, out, size;
00485     bool dynamic;
00486 
00487     int _getch(void);
00488     int _putch(int code);
00489 
00490 public:
00491     charmem(char *mem, size_t size);
00492     charmem(size_t size);
00493     charmem();
00494     virtual ~charmem();
00495 
00496     void release(void);
00497 
00498     void set(char *mem, size_t size);
00499 
00500     void set(size_t size);
00501 
00502     inline void reset(void)
00503         {inp = out = 0;}
00504 
00505     inline void rewind(void)
00506         {inp = 0;}
00507 };
00508 
00509 class __EXPORT chartext : public CharacterProtocol
00510 {
00511 private:
00512     char *pos;
00513     size_t max;
00514 
00515     int _putch(int code);
00516     int _getch(void);
00517 
00518 public:
00519     chartext();
00520     chartext(char *buf);
00521     chartext(char *buf, size_t size);
00522     virtual ~chartext();
00523 };
00524 
00536 class __EXPORT keyassoc : protected mempager
00537 {
00538 private:
00542     class __LOCAL keydata : public NamedObject
00543     {
00544     public:
00545         void *data;
00546         char text[8];
00547 
00548         keydata(keyassoc *assoc, char *id, unsigned max, unsigned bufsize);
00549     };
00550 
00551     friend class keydata;
00552 
00553     unsigned count;
00554     unsigned paths;
00555     size_t keysize;
00556     NamedObject **root;
00557     LinkedObject **list;
00558 
00559 public:
00566     keyassoc(unsigned indexing = 177, size_t max = 0, size_t page = 0);
00567 
00571     ~keyassoc();
00572 
00577     inline unsigned getCount(void)
00578         {return count;};
00579 
00585     inline void *operator()(const char *name)
00586         {return locate(name);};
00587 
00591     void purge(void);
00592 
00598     void *locate(const char *name);
00599 
00607     bool assign(char *name, void *pointer);
00608 
00615     bool create(char *name, void *pointer);
00616 
00623     void *remove(const char *name);
00624 };
00625 
00633 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0>
00634 class assoc_pointer : private keyassoc
00635 {
00636 public:
00640     inline assoc_pointer() : keyassoc(I, M, P) {};
00641 
00646     inline unsigned getCount(void)
00647         {return keyassoc::getCount();};
00648 
00652     inline void purge(void)
00653         {keyassoc::purge();};
00654 
00660     inline T *locate(const char *name)
00661         {return static_cast<T*>(keyassoc::locate(name));};
00662 
00668     inline T *operator()(const char *name)
00669         {return locate(name);};
00670 
00678     inline bool assign(char *name, T *pointer)
00679         {return keyassoc::assign(name, pointer);};
00680 
00687     inline bool create(char *name, T *pointer)
00688         {return keyassoc::create(name, pointer);};
00689 
00695     inline void remove(char *name)
00696         {keyassoc::remove(name);};
00697 
00703     inline unsigned utilization(void)
00704         {return mempager::utilization();};
00705 
00712     inline unsigned getPages(void)
00713         {return mempager::getPages();};
00714 };
00715 
00722 template <typename T>
00723 class pager : private MemoryRedirect, private PagerPool
00724 {
00725 public:
00730     inline pager(mempager *heap = NULL) : MemoryRedirect(heap), PagerPool() {};
00731 
00735     inline ~pager()
00736         {mempager::purge();};
00737 
00742     inline T *operator()(void)
00743         {return new(get(sizeof(T))) T;};
00744 
00749     inline T *operator*()
00750         {return new(get(sizeof(T))) T;};
00751 };
00752 
00758 template <class T, unsigned M = 177>
00759 class keypager : public mempager
00760 {
00761 private:
00762     NamedObject *idx[M];
00763 
00764 public:
00769     inline keypager(size_t size) : mempager(size) {};
00770 
00774     inline ~keypager()
00775         {NamedObject::purge(idx, M); mempager::purge();};
00776 
00783     inline T *get(const char *name) const {
00784         T *node = (static_cast<T*>(NamedObject::map(idx, name, M)));
00785         if(!node) {
00786             node = init<T>(static_cast<T*>(mempager::_alloc(sizeof(T))));
00787             node->NamedObject::add(idx, name, M);
00788         }
00789         return node;
00790     }
00791 
00797     bool test(const char *name) const
00798         {return NamedObject::map(idx, name, M) != NULL;};
00799 
00806     inline T *operator[](const char *name) const
00807         {return get(name);};
00808 
00813     inline T *begin(void) const
00814         {return static_cast<T*>(NamedObject::skip(idx, NULL, M));};
00815 
00821     inline T *next(T *current) const
00822         {return static_cast<T*>(NamedObject::skip(idx, current, M));};
00823 
00828     inline unsigned count(void) const
00829         {return NamedObject::count(idx, M);};
00830 
00837     inline T **index(void) const
00838         {return NamedObject::index(idx, M);};
00839 
00846     inline T **sort(void) const
00847         {return NamedObject::sort(NamedObject::index(idx, M));};
00848 };
00849 
00850 END_NAMESPACE
00851 
00852 #endif