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     protected:
00258         friend class stringpager;
00259 
00260         inline void set(member *node)
00261             {next = node;};
00262 
00263         member(LinkedObject **root, const char *data);
00264         member(const char *data);
00265 
00266     public:
00267         inline const char *operator*() const
00268             {return text;};
00269 
00270         inline const char *get(void) const
00271             {return text;};
00272     };
00273 
00278     stringpager(size_t pagesize = 256);
00279 
00284     inline unsigned count(void)
00285         {return members;};
00286 
00293     const char *get(unsigned item);
00294 
00299     void add(const char *text);
00300 
00306     void add(char **list);
00307 
00312     void clear(void);
00313 
00320     inline const char *operator[](unsigned item)
00321         {return get(item);};
00322 
00328     inline stringpager::member *begin(void)
00329         {return static_cast<stringpager::member *>(root);};
00330 
00335     inline void operator+=(const char *text)
00336         {add(text);};
00337 
00342     inline stringpager& operator<<(const char *text)
00343         {add(text); return *this;};
00344 
00348     void sort(void);
00349 
00350 private:
00351     member *last;
00352 };
00353 
00361 class __EXPORT DirPager : protected stringpager
00362 {
00363 protected:
00364     const char *dir;
00365 
00371     virtual bool filter(const char *filename);
00372 
00378     bool load(const char *path);
00379 
00380 public:
00381     DirPager();
00382 
00383     DirPager(const char *path);
00384 
00385     void operator=(const char *path);
00386 
00387     inline const char *operator*()
00388         {return dir;};
00389 
00390     inline operator bool()
00391         {return dir != NULL;};
00392 
00393     inline bool operator!()
00394         {return dir == NULL;};
00395 
00402     inline const char *operator[](unsigned item)
00403         {return stringpager::get(item);};
00404 
00405     inline const char *get(unsigned item)
00406         {return stringpager::get(item);};
00407 };
00408 
00413 class __EXPORT bufpager : public memalloc, public CharacterProtocol
00414 {
00415 private:
00416     typedef struct cpage {
00417         struct cpage *next;
00418         char *text;
00419         unsigned size, used;
00420     } cpage_t;
00421 
00422     cpage_t *first, *last, *current, *freelist;
00423     unsigned cpos;
00424     unsigned long ccount;
00425 
00426     virtual int _getch(void);
00427     virtual int _putch(int code);
00428 
00429 protected:
00430     virtual void *_alloc(size_t size);
00431 
00432 public:
00436     void reset(void);
00437 
00441     void rewind(void);
00442 
00447     inline unsigned long getUsed(void)
00448         {return ccount;};
00449 
00450     bufpager(size_t page = 0);
00451 };
00452 
00460 class __EXPORT autorelease
00461 {
00462 private:
00463     LinkedObject *pool;
00464 
00465 public:
00469     autorelease();
00470 
00474     ~autorelease();
00475 
00481     void release(void);
00482 
00487     void operator+=(LinkedObject *object);
00488 };
00489 
00500 class __EXPORT PagerObject : public LinkedObject, public CountedObject
00501 {
00502 protected:
00503     friend class PagerPool;
00504 
00505     PagerPool *pager;
00506 
00510     PagerObject();
00511 
00515     void release(void);
00516 
00520     void dealloc(void);
00521 };
00522 
00531 class __EXPORT PagerPool : public MemoryProtocol
00532 {
00533 private:
00534     LinkedObject *freelist;
00535     pthread_mutex_t mutex;
00536 
00537 protected:
00538     PagerPool();
00539     virtual ~PagerPool();
00540 
00541     PagerObject *get(size_t size);
00542 
00543 public:
00548     void put(PagerObject *object);
00549 };
00550 
00551 class __EXPORT charmem : public CharacterProtocol
00552 {
00553 protected:
00554     char *buffer;
00555     size_t inp, out, size;
00556     bool dynamic;
00557 
00558     int _getch(void);
00559     int _putch(int code);
00560 
00561 public:
00562     charmem(char *mem, size_t size);
00563     charmem(size_t size);
00564     charmem();
00565     virtual ~charmem();
00566 
00567     void release(void);
00568 
00569     void set(char *mem, size_t size);
00570 
00571     void set(size_t size);
00572 
00573     inline void reset(void)
00574         {inp = out = 0;}
00575 
00576     inline void rewind(void)
00577         {inp = 0;}
00578 };
00579 
00580 class __EXPORT chartext : public CharacterProtocol
00581 {
00582 private:
00583     char *pos;
00584     size_t max;
00585 
00586     int _putch(int code);
00587     int _getch(void);
00588 
00589 public:
00590     chartext();
00591     chartext(char *buf);
00592     chartext(char *buf, size_t size);
00593     virtual ~chartext();
00594 };
00595 
00607 class __EXPORT keyassoc : protected mempager
00608 {
00609 private:
00613     class __LOCAL keydata : public NamedObject
00614     {
00615     public:
00616         void *data;
00617         char text[8];
00618 
00619         keydata(keyassoc *assoc, char *id, unsigned max, unsigned bufsize);
00620     };
00621 
00622     friend class keydata;
00623 
00624     unsigned count;
00625     unsigned paths;
00626     size_t keysize;
00627     NamedObject **root;
00628     LinkedObject **list;
00629 
00630 public:
00637     keyassoc(unsigned indexing = 177, size_t max = 0, size_t page = 0);
00638 
00642     ~keyassoc();
00643 
00648     inline unsigned getCount(void)
00649         {return count;};
00650 
00656     inline void *operator()(const char *name)
00657         {return locate(name);};
00658 
00662     void purge(void);
00663 
00669     void *locate(const char *name);
00670 
00678     bool assign(char *name, void *pointer);
00679 
00686     bool create(char *name, void *pointer);
00687 
00694     void *remove(const char *name);
00695 };
00696 
00704 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0>
00705 class assoc_pointer : private keyassoc
00706 {
00707 public:
00711     inline assoc_pointer() : keyassoc(I, M, P) {};
00712 
00717     inline unsigned getCount(void)
00718         {return keyassoc::getCount();};
00719 
00723     inline void purge(void)
00724         {keyassoc::purge();};
00725 
00731     inline T *locate(const char *name)
00732         {return static_cast<T*>(keyassoc::locate(name));};
00733 
00739     inline T *operator()(const char *name)
00740         {return locate(name);};
00741 
00749     inline bool assign(char *name, T *pointer)
00750         {return keyassoc::assign(name, pointer);};
00751 
00758     inline bool create(char *name, T *pointer)
00759         {return keyassoc::create(name, pointer);};
00760 
00766     inline void remove(char *name)
00767         {keyassoc::remove(name);};
00768 
00774     inline unsigned utilization(void)
00775         {return mempager::utilization();};
00776 
00783     inline unsigned getPages(void)
00784         {return mempager::getPages();};
00785 };
00786 
00793 template <typename T>
00794 class pager : private MemoryRedirect, private PagerPool
00795 {
00796 public:
00801     inline pager(mempager *heap = NULL) : MemoryRedirect(heap), PagerPool() {};
00802 
00806     inline ~pager()
00807         {mempager::purge();};
00808 
00813     inline T *operator()(void)
00814         {return new(get(sizeof(T))) T;};
00815 
00820     inline T *operator*()
00821         {return new(get(sizeof(T))) T;};
00822 };
00823 
00829 template <class T, unsigned M = 177>
00830 class keypager : public mempager
00831 {
00832 private:
00833     NamedObject *idx[M];
00834 
00835 public:
00840     inline keypager(size_t size) : mempager(size) {};
00841 
00845     inline ~keypager()
00846         {NamedObject::purge(idx, M); mempager::purge();};
00847 
00854     inline T *get(const char *name) const {
00855         T *node = (static_cast<T*>(NamedObject::map(idx, name, M)));
00856         if(!node) {
00857             node = init<T>(static_cast<T*>(mempager::_alloc(sizeof(T))));
00858             node->NamedObject::add(idx, name, M);
00859         }
00860         return node;
00861     }
00862 
00868     bool test(const char *name) const
00869         {return NamedObject::map(idx, name, M) != NULL;};
00870 
00877     inline T *operator[](const char *name) const
00878         {return get(name);};
00879 
00884     inline T *begin(void) const
00885         {return static_cast<T*>(NamedObject::skip(idx, NULL, M));};
00886 
00892     inline T *next(T *current) const
00893         {return static_cast<T*>(NamedObject::skip(idx, current, M));};
00894 
00899     inline unsigned count(void) const
00900         {return NamedObject::count(idx, M);};
00901 
00908     inline T **index(void) const
00909         {return NamedObject::index(idx, M);};
00910 
00917     inline T **sort(void) const
00918         {return NamedObject::sort(NamedObject::index(idx, M));};
00919 };
00920 
00924 typedef stringpager stringlist_t;
00925 
00929 typedef stringpager::member stringlistitem_t;
00930 
00934 typedef DirPager dirlist_t;
00935 
00936 
00937 END_NAMESPACE
00938 
00939 #endif