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 
00238 class __EXPORT bufpager : public memalloc, public CharacterProtocol
00239 {
00240 private:
00241     typedef struct cpage {
00242         struct cpage *next;
00243         char *text;
00244         unsigned size, used;
00245     } cpage_t;
00246 
00247     cpage_t *first, *last, *current, *freelist;
00248     unsigned cpos;
00249     unsigned long ccount;
00250 
00251     virtual int _getch(void);
00252     virtual int _putch(int code);
00253 
00254 protected:
00255     virtual void *_alloc(size_t size);
00256 
00257 public:
00261     void reset(void);
00262 
00266     void rewind(void);
00267 
00272     inline unsigned long getUsed(void)
00273         {return ccount;};
00274 
00275     bufpager(size_t page = 0);
00276 };
00277 
00285 class __EXPORT autorelease
00286 {
00287 private:
00288     LinkedObject *pool;
00289 
00290 public:
00294     autorelease();
00295 
00299     ~autorelease();
00300 
00306     void release(void);
00307 
00312     void operator+=(LinkedObject *object);
00313 };
00314 
00325 class __EXPORT PagerObject : public LinkedObject, public CountedObject
00326 {
00327 protected:
00328     friend class PagerPool;
00329 
00330     PagerPool *pager;
00331 
00335     PagerObject();
00336 
00340     void release(void);
00341 
00345     void dealloc(void);
00346 };  
00347 
00356 class __EXPORT PagerPool : public MemoryProtocol
00357 {
00358 private:
00359     LinkedObject *freelist;
00360     pthread_mutex_t mutex;
00361 
00362 protected:
00363     PagerPool();
00364     ~PagerPool();
00365 
00366     PagerObject *get(size_t size);
00367 
00368 public:
00373     void put(PagerObject *object);
00374 };
00375 
00376 class __EXPORT charmem : public CharacterProtocol
00377 {
00378 protected:
00379     char *buffer;
00380     size_t inp, out, size;
00381     bool dynamic;
00382 
00383     int _getch(void);
00384     int _putch(int code);
00385 
00386 public:
00387     charmem(char *mem, size_t size);
00388     charmem(size_t size);
00389     charmem();
00390     ~charmem();
00391 
00392     void release(void);
00393     
00394     void set(char *mem, size_t size);
00395 
00396     void set(size_t size);
00397 
00398     inline void reset(void)
00399         {inp = out = 0;}
00400 
00401     inline void rewind(void)
00402         {inp = 0;}
00403 };
00404 
00405 class __EXPORT chartext : public CharacterProtocol
00406 {
00407 private:
00408     char *pos;
00409     size_t max;
00410 
00411     int _putch(int code);
00412     int _getch(void);
00413 
00414 public:
00415     chartext();
00416     chartext(char *buf);
00417     chartext(char *buf, size_t size);   
00418 };
00419 
00431 class __EXPORT keyassoc : protected mempager
00432 {
00433 private:
00437     class __LOCAL keydata : public NamedObject
00438     {
00439     public:
00440         void *data;
00441         char text[8];
00442 
00443         keydata(keyassoc *assoc, char *id, unsigned max, unsigned bufsize);
00444     };
00445 
00446     friend class keydata;
00447 
00448     unsigned count;
00449     unsigned paths;
00450     size_t keysize;
00451     NamedObject **root;
00452     LinkedObject **list;
00453 
00454 public:
00461     keyassoc(unsigned indexing = 177, size_t max = 0, size_t page = 0);
00462 
00466     ~keyassoc();
00467 
00472     inline unsigned getCount(void)
00473         {return count;};
00474 
00480     inline void *operator()(const char *name)
00481         {return locate(name);};
00482 
00486     void purge(void);
00487 
00493     void *locate(const char *name);
00494 
00502     bool assign(char *name, void *pointer);
00503 
00510     bool create(char *name, void *pointer);
00511 
00518     void *remove(const char *name);
00519 };
00520 
00528 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0>
00529 class assoc_pointer : private keyassoc
00530 {
00531 public:
00535     inline assoc_pointer() : keyassoc(I, M, P) {};
00536 
00541     inline unsigned getCount(void)
00542         {return keyassoc::getCount();};
00543 
00547     inline void purge(void)
00548         {keyassoc::purge();};
00549 
00555     inline T *locate(const char *name)
00556         {return static_cast<T*>(keyassoc::locate(name));};
00557 
00563     inline T *operator()(const char *name)
00564         {return locate(name);};
00565 
00573     inline bool assign(char *name, T *pointer)
00574         {return keyassoc::assign(name, pointer);};
00575 
00582     inline bool create(char *name, T *pointer)
00583         {return keyassoc::create(name, pointer);};
00584 
00590     inline void remove(char *name)
00591         {keyassoc::remove(name);};
00592 
00598     inline unsigned utilization(void)
00599         {return mempager::utilization();};
00600 
00607     inline unsigned getPages(void)
00608         {return mempager::getPages();};
00609 };
00610 
00617 template <typename T>
00618 class pager : private MemoryRedirect, private PagerPool
00619 {
00620 public:
00625     inline pager(mempager *heap = NULL) : MemoryRedirect(heap), PagerPool() {};
00626 
00630     inline ~pager()
00631         {mempager::purge();};
00632 
00637     inline T *operator()(void)
00638         {return new(get(sizeof(T))) T;};
00639 
00644     inline T *operator*()
00645         {return new(get(sizeof(T))) T;};
00646 };
00647 
00653 template <class T, unsigned M = 177>
00654 class keypager : public mempager
00655 {
00656 private:
00657     NamedObject *idx[M];
00658 
00659 public:
00664     inline keypager(size_t size) : mempager(size) {};
00665 
00669     inline ~keypager()
00670         {NamedObject::purge(idx, M); mempager::purge();};
00671 
00678     inline T *get(const char *name) const {
00679         T *node = (static_cast<T*>(NamedObject::map(idx, name, M)));
00680         if(!node) {
00681             node = init<T>(static_cast<T*>(mempager::_alloc(sizeof(T))));
00682             node->NamedObject::add(idx, name, M);
00683         }
00684         return node;
00685     }
00686 
00692     bool test(const char *name) const
00693         {return NamedObject::map(idx, name, M) != NULL;};
00694 
00701     inline T *operator[](const char *name) const
00702         {return get(name);};
00703 
00708     inline T *begin(void) const
00709         {return static_cast<T*>(NamedObject::skip(idx, NULL, M));};
00710 
00716     inline T *next(T *current) const
00717         {return static_cast<T*>(NamedObject::skip(idx, current, M));};
00718 
00723     inline unsigned count(void) const
00724         {return NamedObject::count(idx, M);};
00725 
00732     inline T **index(void) const
00733         {return NamedObject::index(idx, M);};
00734 
00741     inline T **sort(void) const
00742         {return NamedObject::sort(NamedObject::index(idx, M));};
00743 }; 
00744 
00745 END_NAMESPACE
00746 
00747 #endif