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 #ifndef _UCOMMON_STRING_H_
00046 #include <ucommon/string.h>
00047 #endif
00048 
00049 NAMESPACE_UCOMMON
00050 
00051 class PagerPool;
00052 
00060 class __EXPORT memalloc : public MemoryProtocol
00061 {
00062 private:
00063     friend class bufpager;
00064 
00065     size_t pagesize, align;
00066     unsigned count;
00067 
00068     typedef struct mempage {
00069         struct mempage *next;
00070         union {
00071             void *memalign;
00072             unsigned used;
00073         };
00074     }   page_t;
00075 
00076     page_t *page;
00077 
00078 protected:
00079     unsigned limit;
00080 
00085     page_t *pager(void);
00086 
00090     virtual void fault(void) const;
00091 
00092 public:
00097     memalloc(size_t page = 0);
00098 
00102     virtual ~memalloc();
00103 
00108     inline unsigned pages(void) const
00109         {return count;}
00110 
00118     inline unsigned max(void) const
00119         {return limit;}
00120 
00125     inline unsigned size(void) const
00126         {return pagesize;}
00127 
00138     unsigned utilization(void) const;
00139 
00143     void purge(void);
00144 
00152     virtual void *_alloc(size_t size);
00153 };
00154 
00175 class __EXPORT mempager : public memalloc, public LockingProtocol
00176 {
00177 private:
00178     pthread_mutex_t mutex;
00179 
00180 protected:
00187     virtual void _lock(void);
00188 
00192     virtual void _unlock(void);
00193 
00194 public:
00199     mempager(size_t page = 0);
00200 
00204     virtual ~mempager();
00205 
00216     unsigned utilization(void);
00217 
00221     void purge(void);
00222 
00230     virtual void dealloc(void *memory);
00231 
00240     virtual void *_alloc(size_t size);
00241 };
00242 
00243 class __EXPORT ObjectPager : protected memalloc
00244 {
00245 public:
00246     class __EXPORT member : public LinkedObject
00247     {
00248     private:
00249         void *mem;
00250 
00251     protected:
00252         friend class ObjectPager;
00253 
00254         inline void set(member *node)
00255             {Next = node;};
00256 
00257         inline void *get(void) const
00258             {return mem;};
00259 
00260         member(LinkedObject **root);
00261         member();
00262 
00263     public:
00264         inline void *operator*() const
00265             {return mem;};
00266     };
00267 
00268 private:
00269     unsigned members;
00270     LinkedObject *root;
00271     size_t typesize;
00272     member *last;
00273     void **index;
00274 
00275 protected:
00276     ObjectPager(size_t objsize, size_t pagesize = 256);
00277 
00284     void *get(unsigned item) const;
00285 
00290     void *add(void);
00291 
00292     void *push(void);
00293 
00298     void *pull(void);
00299 
00304     void *pop(void);
00305 
00310     void *invalid(void) const;
00311 
00312 public:
00317     void clear(void);
00318 
00324     inline ObjectPager::member *begin(void)
00325         {return static_cast<ObjectPager::member *>(root);};
00326 
00327     inline operator bool() const
00328         {return members > 0;}
00329 
00330     inline bool operator!() const
00331         {return !members;}
00332 
00337     inline unsigned count(void) const
00338         {return members;};
00339 
00343     typedef linked_pointer<ObjectPager::member> iterator;
00344 
00345     inline size_t size(void)
00346         {return memalloc::size();}
00347 
00348     inline unsigned pages(void)
00349         {return memalloc::pages();}
00350 
00351 protected:
00356     void **list(void);
00357 };
00358 
00364 class __EXPORT StringPager : protected memalloc
00365 {
00366 private:
00367     unsigned members;
00368     LinkedObject *root;
00369 
00370 protected:
00371     virtual const char *invalid(void) const;
00372 
00373 public:
00381     virtual bool filter(char *text, size_t size);
00382 
00389     class __EXPORT member : public LinkedObject
00390     {
00391     private:
00392         const char *text;
00393 
00394     protected:
00395         friend class StringPager;
00396 
00397         inline void set(member *node)
00398             {Next = node;};
00399 
00400         member(LinkedObject **root, const char *data);
00401         member(const char *data);
00402 
00403     public:
00404         inline const char *operator*() const
00405             {return text;};
00406 
00407         inline const char *get(void) const
00408             {return text;};
00409     };
00410 
00415     StringPager(size_t pagesize = 256);
00416 
00417     StringPager(char **list, size_t pagesize = 256);
00418 
00423     inline unsigned count(void) const
00424         {return members;};
00425 
00432     const char *get(unsigned item) const;
00433 
00439     void set(unsigned item, const char *string);
00440 
00445     void add(const char *text);
00446 
00451     void push(const char *text);
00452 
00457     void push(char **text);
00458 
00463     const char *pull(void);
00464 
00469     const char *pop(void);
00470 
00476     void add(char **list);
00477 
00483     void set(char **list);
00484 
00489     void clear(void);
00490 
00497     inline const char *operator[](unsigned item) const
00498         {return get(item);};
00499 
00500     inline const char *at(unsigned item) const
00501         {return get(item);};
00502 
00508     inline StringPager::member *begin(void) const
00509         {return static_cast<StringPager::member *>(root);};
00510 
00515     inline void operator+=(const char *text)
00516         {add(text);};
00517 
00522     inline StringPager& operator<<(const char *text)
00523         {add(text); return *this;}
00524 
00525     inline StringPager& operator>>(const char *text)
00526         {push(text); return *this;}
00527 
00531     void sort(void);
00532 
00537     char **list(void);
00538 
00547     unsigned token(const char *text, const char *list, const char *quote = NULL, const char *end = NULL);
00548 
00549     unsigned split(const char *text, const char *string, unsigned flags = 0);
00550 
00551     unsigned split(stringex_t& expr, const char *string, unsigned flags = 0);
00552 
00553     String join(const char *prefix = NULL, const char *middle = NULL, const char *suffix = NULL);
00554 
00555     inline operator bool()
00556         {return members > 0;}
00557 
00558     inline bool operator!()
00559         {return !members;}
00560 
00561     inline StringPager& operator=(char **list)
00562         {set(list); return *this;}
00563 
00564     inline const char *operator*()
00565         {return pull();}
00566 
00567     inline operator char **()
00568         {return list();};
00569 
00573     typedef linked_pointer<StringPager::member> iterator;
00574 
00575     inline size_t size(void)
00576         {return memalloc::size();}
00577 
00578     inline unsigned pages(void)
00579         {return memalloc::pages();}
00580 
00581 private:
00582     member *last;
00583     char **index;
00584 };
00585 
00593 class __EXPORT DirPager : protected StringPager
00594 {
00595 protected:
00596     const char *dir;
00597 
00605     virtual bool filter(char *filename, size_t size);
00606 
00612     bool load(const char *path);
00613 
00614 public:
00615     DirPager();
00616 
00617     DirPager(const char *path);
00618 
00619     void operator=(const char *path);
00620 
00621     inline const char *operator*() const
00622         {return dir;};
00623 
00624     inline operator bool() const
00625         {return dir != NULL;};
00626 
00627     inline bool operator!() const
00628         {return dir == NULL;};
00629 
00630     inline unsigned count(void) const
00631         {return StringPager::count();};
00632 
00639     inline const char *operator[](unsigned item) const
00640         {return StringPager::get(item);};
00641 
00642     inline const char *get(unsigned item) const
00643         {return StringPager::get(item);};
00644 
00645     inline const char *at(unsigned item) const
00646         {return StringPager::get(item);};
00647 
00648     inline size_t size(void)
00649         {return memalloc::size();}
00650 
00651     inline unsigned pages(void)
00652         {return memalloc::pages();}
00653 };
00654 
00659 class __EXPORT bufpager : public memalloc, public CharacterProtocol
00660 {
00661 private:
00662     typedef struct cpage {
00663         struct cpage *next;
00664         char *text;
00665         unsigned size, used;
00666     } cpage_t;
00667 
00668     cpage_t *first, *last, *current, *freelist;
00669     unsigned cpos;
00670     unsigned long ccount;
00671     bool eom;       /* null written or out of memory */
00672 
00673     virtual int _getch(void);
00674     virtual int _putch(int code);
00675 
00676 protected:
00677     virtual void *_alloc(size_t size);
00678 
00679 public:
00683     void reset(void);
00684 
00688     void rewind(void);
00689 
00694     char *dup(void);
00695 
00700     void set(const char *text);
00701 
00706     void add(const char *text);
00707 
00714     size_t get(char *text, size_t size);
00715 
00721     void put(const char *text, size_t size);
00722 
00727     inline unsigned long used(void) const
00728         {return ccount;}
00729 
00734     inline char *operator *()
00735         {return dup();}
00736 
00741     inline bufpager& operator<<(const char *text)
00742         {add(text); return *this;};
00743 
00744     bufpager(size_t page = 0);
00745 
00751     char *request(size_t *iosize);
00752 
00759     char *copy(size_t *iosize);
00760 
00765     void update(size_t size);
00766 
00771     inline bool operator!()
00772         {return eom;}
00773 
00778     inline operator bool()
00779         {return !eom;}
00780 };
00781 
00789 class __EXPORT autorelease
00790 {
00791 private:
00792     LinkedObject *pool;
00793 
00794 public:
00798     autorelease();
00799 
00803     ~autorelease();
00804 
00810     void release(void);
00811 
00816     void operator+=(LinkedObject *object);
00817 };
00818 
00829 class __EXPORT PagerObject : public LinkedObject, public CountedObject
00830 {
00831 protected:
00832     friend class PagerPool;
00833 
00834     PagerPool *pager;
00835 
00839     PagerObject();
00840 
00844     void reset(void);
00845 
00849     void release(void);
00850 
00854     void dealloc(void);
00855 };
00856 
00865 class __EXPORT PagerPool : public MemoryProtocol
00866 {
00867 private:
00868     LinkedObject *freelist;
00869     pthread_mutex_t mutex;
00870 
00871 protected:
00872     PagerPool();
00873     virtual ~PagerPool();
00874 
00875     PagerObject *get(size_t size);
00876 
00877 public:
00882     void put(PagerObject *object);
00883 };
00884 
00885 class __EXPORT charmem : public CharacterProtocol
00886 {
00887 protected:
00888     char *buffer;
00889     size_t inp, out, size;
00890     bool dynamic;
00891 
00892     int _getch(void);
00893     int _putch(int code);
00894 
00895 public:
00896     charmem(char *mem, size_t size);
00897     charmem(size_t size);
00898     charmem();
00899     virtual ~charmem();
00900 
00901     void release(void);
00902 
00903     void set(char *mem, size_t size);
00904 
00905     void set(size_t size);
00906 
00907     inline void reset(void)
00908         {inp = out = 0;}
00909 
00910     inline void rewind(void)
00911         {inp = 0;}
00912 };
00913 
00914 class __EXPORT chartext : public CharacterProtocol
00915 {
00916 private:
00917     char *pos;
00918     size_t max;
00919 
00920     int _putch(int code);
00921     int _getch(void);
00922 
00923 public:
00924     chartext();
00925     chartext(char *buf);
00926     chartext(char *buf, size_t size);
00927     virtual ~chartext();
00928 };
00929 
00941 class __EXPORT keyassoc : protected mempager
00942 {
00943 private:
00947     class __LOCAL keydata : public NamedObject
00948     {
00949     public:
00950         void *data;
00951         char text[8];
00952 
00953         keydata(keyassoc *assoc, const char *id, unsigned max, unsigned bufsize);
00954     };
00955 
00956     friend class keydata;
00957 
00958     unsigned keycount;
00959     unsigned paths;
00960     size_t keysize;
00961     NamedObject **root;
00962     LinkedObject **list;
00963 
00964 protected:
00971     void *allocate(const char *name, size_t size);
00972 
00973 public:
00980     keyassoc(unsigned indexing = 177, size_t max = 0, size_t page = 0);
00981 
00985     ~keyassoc();
00986 
00991     inline unsigned count(void) const
00992         {return keycount;};
00993 
00999     inline void *operator()(const char *name)
01000         {return locate(name);};
01001 
01005     void purge(void);
01006 
01012     void *locate(const char *name);
01013 
01021     bool assign(const char *name, void *pointer);
01022 
01029     bool create(const char *name, void *pointer);
01030 
01037     void *remove(const char *name);
01038 };
01039 
01040 template <class T, size_t P = 0>
01041 class listof : private ObjectPager
01042 {
01043 public:
01044     inline listof() : ObjectPager(sizeof(T), P) {};
01045 
01046     inline T& operator[](unsigned item) const
01047         {return (T&)ObjectPager::get(item);}
01048 
01049     inline T* operator()(unsigned item) const
01050         {return (T*)ObjectPager::get(item);}
01051 
01052     inline const T& at(unsigned item) const
01053         {return (const T&)ObjectPager::get(item);}
01054 
01055     inline T* pull(void)
01056         {return (T*)ObjectPager::pull();}
01057 
01058     inline T* pop(void)
01059         {return (T*)ObjectPager::pop();}
01060 
01061     inline operator T**()
01062         {return (T**)ObjectPager::list();}
01063 
01064     inline T** list(void)
01065         {return (T**)ObjectPager::list();}
01066 
01067     inline T* operator++(void)
01068         {T* tmp = ObjectPager::add(); if(tmp) new((caddr_t)tmp) T; return tmp;}
01069 
01070     inline T* add(const T& object)
01071         {T* tmp = ObjectPager::add(); if(tmp) new((caddr_t)tmp) T(object); return tmp;}
01072 
01073     inline T* push(const T& object)
01074         {T* tmp = ObjectPager::push(); if(tmp) new((caddr_t)tmp) T(object); return tmp;}
01075 
01076     inline listof& operator<<(const T& object)
01077         {T* tmp = ObjectPager::add(); if(tmp) new((caddr_t)tmp) T(object); return *this;}
01078 
01079     inline listof& operator>>(const T& object)
01080         {T* tmp = ObjectPager::push(); if(tmp) new((caddr_t)tmp) T(object); return *this;}
01081 
01082 };
01083 
01084 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0>
01085 class mapof : private keyassoc
01086 {
01087 public:
01091     inline mapof() : keyassoc(I, M, P) {};
01092 
01097     inline unsigned count(void) const
01098         {return keyassoc::count();};
01099 
01103     inline void purge(void)
01104         {keyassoc::purge();};
01105 
01111     inline T *locate(const char *name)
01112         {return static_cast<T*>(keyassoc::locate(name));}
01113 
01114     inline T *operator[](const char *name)
01115         {return static_cast<T*>(keyassoc::locate(name));}
01116 
01122     inline T *operator()(const char *name)
01123         {return locate(name);};
01124 
01129     inline T *map(const char *name)
01130         {T *tmp = keyassoc::allocate(name, sizeof(T)); if(tmp) new((caddr_t)tmp) T;}
01131 
01137     inline void unmap(const char *name)
01138         {keyassoc::remove(name);};
01139 
01145     inline unsigned utilization(void)
01146         {return mempager::utilization();};
01147 
01154     inline unsigned pages(void) const
01155         {return mempager::pages();};
01156 };
01157 
01165 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0>
01166 class assoc_pointer : private keyassoc
01167 {
01168 public:
01172     inline assoc_pointer() : keyassoc(I, M, P) {};
01173 
01178     inline unsigned count(void) const
01179         {return keyassoc::count();}
01180 
01184     inline void purge(void)
01185         {keyassoc::purge();}
01186 
01192     inline T *locate(const char *name)
01193         {return static_cast<T*>(keyassoc::locate(name));}
01194 
01195     inline T *operator[](const char *name)
01196         {return static_cast<T*>(keyassoc::locate(name));}
01197 
01198 
01204     inline T *operator()(const char *name)
01205         {return locate(name);}
01206 
01214     inline bool assign(char *name, T *pointer)
01215         {return keyassoc::assign(name, pointer);}
01216 
01223     inline bool create(char *name, T *pointer)
01224         {return keyassoc::create(name, pointer);}
01225 
01231     inline void remove(char *name)
01232         {keyassoc::remove(name);}
01233 
01239     inline unsigned utilization(void) const
01240         {return mempager::utilization();}
01241 
01248     inline unsigned pages(void) const
01249         {return mempager::pages();}
01250 };
01251 
01258 template <typename T>
01259 class pager : private MemoryRedirect, private PagerPool
01260 {
01261 public:
01266     inline pager(mempager *heap = NULL) : MemoryRedirect(heap), PagerPool() {};
01267 
01272     inline T *operator()(void)
01273         {return new(get(sizeof(T))) T;};
01274 
01279     inline T *operator*()
01280         {return new(get(sizeof(T))) T;};
01281 };
01282 
01288 template <class T, unsigned M = 177>
01289 class keypager : public mempager
01290 {
01291 private:
01292     NamedObject *idx[M];
01293 
01294 public:
01299     inline keypager(size_t size) : mempager(size) {};
01300 
01304     inline ~keypager()
01305         {NamedObject::purge(idx, M); mempager::purge();};
01306 
01313     inline T *get(const char *name) const {
01314         T *node = (static_cast<T*>(NamedObject::map(idx, name, M)));
01315         if(!node) {
01316             node = init<T>(static_cast<T*>(mempager::_alloc(sizeof(T))));
01317             node->NamedObject::add(idx, name, M);
01318         }
01319         return node;
01320     }
01321 
01327     bool test(const char *name) const
01328         {return NamedObject::map(idx, name, M) != NULL;};
01329 
01336     inline T *operator[](const char *name) const
01337         {return get(name);};
01338 
01343     inline T *begin(void) const
01344         {return static_cast<T*>(NamedObject::skip(idx, NULL, M));};
01345 
01351     inline T *next(T *current) const
01352         {return static_cast<T*>(NamedObject::skip(idx, current, M));};
01353 
01358     inline unsigned count(void) const
01359         {return NamedObject::count(idx, M);};
01360 
01367     inline T **index(void) const
01368         {return NamedObject::index(idx, M);};
01369 
01376     inline T **sort(void) const
01377         {return NamedObject::sort(NamedObject::index(idx, M));};
01378 
01382     typedef linked_pointer<T> iterator;
01383 };
01384 
01388 typedef StringPager stringlist_t;
01389 
01393 typedef StringPager::member stringlistitem_t;
01394 
01398 typedef DirPager dirlist_t;
01399 
01400 inline const char *shift(stringlist_t& list)
01401     {return list.pull();}
01402 
01403 inline void unshift(stringlist_t& list, const char *text)
01404     {list.push(text);}
01405 
01406 
01407 inline String str(StringPager& list, const char *prefix = NULL, const char *middle = NULL, const char *suffix = NULL)
01408     {return list.join(prefix, middle, suffix);}
01409 
01410 END_NAMESPACE
01411 
01412 #endif

Generated on 14 Aug 2013 for UCommon by  doxygen 1.4.7