UCommon
/usr/src/RPM/BUILD/ucommon-6.3.3/inc/ucommon/memory.h
Go to the documentation of this file.
00001 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
00002 // Copyright (C) 2015 Cherokees of Idaho.
00003 //
00004 // This file is part of GNU uCommon C++.
00005 //
00006 // GNU uCommon C++ is free software: you can redistribute it and/or modify
00007 // it under the terms of the GNU Lesser General Public License as published
00008 // by the Free Software Foundation, either version 3 of the License, or
00009 // (at your option) any later version.
00010 //
00011 // GNU uCommon C++ is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public License
00017 // along with GNU uCommon C++.  If not, see <http://www.gnu.org/licenses/>.
00018 
00031 #ifndef _UCOMMON_MEMORY_H_
00032 #define _UCOMMON_MEMORY_H_
00033 
00034 #ifndef _UCOMMON_CONFIG_H_
00035 #include <ucommon/platform.h>
00036 #endif
00037 
00038 #ifndef _UCOMMON_PROTOCOLS_H_
00039 #include <ucommon/protocols.h>
00040 #endif
00041 
00042 #ifndef  _UCOMMON_LINKED_H_
00043 #include <ucommon/linked.h>
00044 #endif
00045 
00046 #ifndef _UCOMMON_STRING_H_
00047 #include <ucommon/string.h>
00048 #endif
00049 
00050 namespace ucommon {
00051 
00052 class PagerPool;
00053 
00061 class __EXPORT memalloc : public MemoryProtocol
00062 {
00063 private:
00064     friend class bufpager;
00065 
00066     size_t pagesize, align;
00067     unsigned count;
00068 
00069     typedef struct mempage {
00070         struct mempage *next;
00071         union {
00072             void *memalign;
00073             unsigned used;
00074         };
00075     }   page_t;
00076 
00077     page_t *page;
00078 
00079 protected:
00080     unsigned limit;
00081 
00086     page_t *pager(void);
00087 
00091     virtual void fault(void) const;
00092 
00093 public:
00098     memalloc(size_t page = 0);
00099 
00103     virtual ~memalloc();
00104 
00109     inline unsigned pages(void) const
00110         {return count;}
00111 
00119     inline unsigned max(void) const
00120         {return limit;}
00121 
00126     inline unsigned size(void) const
00127         {return pagesize;}
00128 
00139     unsigned utilization(void) const;
00140 
00144     void purge(void);
00145 
00153     virtual void *_alloc(size_t size);
00154 };
00155 
00176 class __EXPORT mempager : public memalloc, public LockingProtocol
00177 {
00178 private:
00179     mutable pthread_mutex_t mutex;
00180 
00181 protected:
00188     virtual void _lock(void);
00189 
00193     virtual void _unlock(void);
00194 
00195 public:
00200     mempager(size_t page = 0);
00201 
00205     virtual ~mempager();
00206 
00217     unsigned utilization(void);
00218 
00222     void purge(void);
00223 
00231     virtual void dealloc(void *memory);
00232 
00241     virtual void *_alloc(size_t size);
00242 };
00243 
00244 class __EXPORT ObjectPager : protected memalloc
00245 {
00246 public:
00247     class __EXPORT member : public LinkedObject
00248     {
00249     private:
00250         void *mem;
00251 
00252     protected:
00253         friend class ObjectPager;
00254 
00255         inline void set(member *node)
00256             {Next = node;}
00257 
00258         inline void *get(void) const
00259             {return mem;}
00260 
00261         member(LinkedObject **root);
00262         member();
00263 
00264     public:
00265         inline void *operator*() const
00266             {return mem;}
00267     };
00268 
00269 private:
00270     unsigned members;
00271     LinkedObject *root;
00272     size_t typesize;
00273     member *last;
00274     void **index;
00275 
00276 protected:
00277     ObjectPager(size_t objsize, size_t pagesize = 256);
00278 
00285     void *get(unsigned item) const;
00286 
00291     void *add(void);
00292 
00293     void *push(void);
00294 
00299     void *pull(void);
00300 
00305     void *pop(void);
00306 
00311     void *invalid(void) const;
00312 
00313 public:
00318     void clear(void);
00319 
00325     inline ObjectPager::member *begin(void)
00326         {return static_cast<ObjectPager::member *>(root);}
00327 
00328     inline operator bool() const
00329         {return members > 0;}
00330 
00331     inline bool operator!() const
00332         {return !members;}
00333 
00338     inline unsigned count(void) const
00339         {return members;}
00340 
00344     typedef linked_pointer<ObjectPager::member> iterator;
00345 
00346     inline size_t size(void)
00347         {return memalloc::size();}
00348 
00349     inline unsigned pages(void)
00350         {return memalloc::pages();}
00351 
00352 protected:
00357     void **list(void);
00358 };
00359 
00365 class __EXPORT StringPager : protected memalloc
00366 {
00367 private:
00368     unsigned members;
00369     LinkedObject *root;
00370 
00371 protected:
00372     virtual const char *invalid(void) const;
00373 
00374 public:
00382     virtual bool filter(char *text, size_t size);
00383 
00390     class __EXPORT member : public LinkedObject
00391     {
00392     private:
00393         const char *text;
00394 
00395     protected:
00396         friend class StringPager;
00397 
00398         inline void set(member *node)
00399             {Next = node;}
00400 
00401         member(LinkedObject **root, const char *data);
00402         member(const char *data);
00403 
00404     public:
00405         inline const char *operator*() const
00406             {return text;}
00407 
00408         inline const char *get(void) const
00409             {return text;}
00410     };
00411 
00416     StringPager(size_t pagesize = 256);
00417 
00418     StringPager(char **list, size_t pagesize = 256);
00419 
00424     inline unsigned count(void) const
00425         {return members;}
00426 
00433     const char *get(unsigned item) const;
00434 
00440     void set(unsigned item, const char *string);
00441 
00446     void add(const char *text);
00447 
00452     void push(const char *text);
00453 
00458     void push(char **text);
00459 
00464     const char *pull(void);
00465 
00470     const char *pop(void);
00471 
00477     void add(char **list);
00478 
00484     void set(char **list);
00485 
00490     void clear(void);
00491 
00498     inline const char *operator[](unsigned item) const
00499         {return get(item);}
00500 
00501     inline const char *at(unsigned item) const
00502         {return get(item);}
00503 
00509     inline StringPager::member *begin(void) const
00510         {return static_cast<StringPager::member *>(root);}
00511 
00516     inline void operator+=(const char *text)
00517         {add(text);}
00518 
00523     inline StringPager& operator<<(const char *text)
00524         {add(text); return *this;}
00525 
00526     inline StringPager& operator>>(const char *text)
00527         {push(text); return *this;}
00528 
00532     void sort(void);
00533 
00538     char **list(void);
00539 
00548     unsigned token(const char *text, const char *list, const char *quote = NULL, const char *end = NULL);
00549 
00550     unsigned split(const char *text, const char *string, unsigned flags = 0);
00551 
00552     unsigned split(stringex_t& expr, const char *string, unsigned flags = 0);
00553 
00554     String join(const char *prefix = NULL, const char *middle = NULL, const char *suffix = NULL);
00555 
00556     inline operator bool()
00557         {return members > 0;}
00558 
00559     inline bool operator!()
00560         {return !members;}
00561 
00562     inline StringPager& operator=(char **list)
00563         {set(list); return *this;}
00564 
00565     inline const char *operator*()
00566         {return pull();}
00567 
00568     inline operator char **()
00569         {return list();}
00570 
00574     typedef linked_pointer<StringPager::member> iterator;
00575 
00576     inline size_t size(void) const
00577         {return memalloc::size();}
00578 
00579     inline unsigned pages(void) const
00580         {return memalloc::pages();}
00581 
00582 private:
00583     member *last;
00584     char **index;
00585 };
00586 
00594 class __EXPORT DirPager : protected StringPager
00595 {
00596 protected:
00597     const char *dir;
00598 
00606     virtual bool filter(char *filename, size_t size);
00607 
00613     bool load(const char *path);
00614 
00615 public:
00616     DirPager();
00617 
00618     DirPager(const char *path);
00619 
00620     void operator=(const char *path);
00621 
00622     inline const char *operator*() const
00623         {return dir;}
00624 
00625     inline operator bool() const
00626         {return dir != NULL;}
00627 
00628     inline bool operator!() const
00629         {return dir == NULL;}
00630 
00631     inline unsigned count(void) const
00632         {return StringPager::count();}
00633 
00640     inline const char *operator[](unsigned item) const
00641         {return StringPager::get(item);}
00642 
00643     inline const char *get(unsigned item) const
00644         {return StringPager::get(item);}
00645 
00646     inline const char *at(unsigned item) const
00647         {return StringPager::get(item);}
00648 
00649     inline size_t size(void) const
00650         {return memalloc::size();}
00651 
00652     inline unsigned pages(void) const
00653         {return memalloc::pages();}
00654 };
00655 
00660 class __EXPORT bufpager : public memalloc, public CharacterProtocol
00661 {
00662 private:
00663     typedef struct cpage {
00664         struct cpage *next;
00665         char *text;
00666         unsigned size, used;
00667     } cpage_t;
00668 
00669     cpage_t *first, *last, *current, *freelist;
00670     unsigned cpos;
00671     unsigned long ccount;
00672     bool eom;       /* null written or out of memory */
00673 
00674     virtual int _getch(void);
00675     virtual int _putch(int code);
00676 
00677 protected:
00678     virtual void *_alloc(size_t size);
00679 
00680 public:
00684     void reset(void);
00685 
00689     void rewind(void);
00690 
00695     char *dup(void);
00696 
00701     void set(const char *text);
00702 
00707     void add(const char *text);
00708 
00715     size_t get(char *text, size_t size);
00716 
00722     void put(const char *text, size_t size);
00723 
00728     inline unsigned long used(void) const
00729         {return ccount;}
00730 
00735     inline char *operator *()
00736         {return dup();}
00737 
00742     inline bufpager& operator<<(const char *text)
00743         {add(text); return *this;}
00744 
00745     bufpager(size_t page = 0);
00746 
00752     char *request(size_t *iosize);
00753 
00760     char *copy(size_t *iosize);
00761 
00766     void update(size_t size);
00767 
00772     inline bool operator!() const
00773         {return eom;}
00774 
00779     inline operator bool() const
00780         {return !eom;}
00781 };
00782 
00790 class __EXPORT autorelease
00791 {
00792 private:
00793     LinkedObject *pool;
00794 
00795 public:
00799     autorelease();
00800 
00804     ~autorelease();
00805 
00811     void release(void);
00812 
00817     void operator+=(LinkedObject *object);
00818 };
00819 
00830 class __EXPORT PagerObject : public LinkedObject, public CountedObject
00831 {
00832 protected:
00833     friend class PagerPool;
00834 
00835     PagerPool *pager;
00836 
00840     PagerObject();
00841 
00845     void reset(void);
00846 
00850     void release(void);
00851 
00855     void dealloc(void);
00856 };
00857 
00866 class __EXPORT PagerPool : public MemoryProtocol
00867 {
00868 private:
00869     LinkedObject *freelist;
00870     mutable pthread_mutex_t mutex;
00871 
00872 protected:
00873     PagerPool();
00874     virtual ~PagerPool();
00875 
00876     PagerObject *get(size_t size);
00877 
00878 public:
00883     void put(PagerObject *object);
00884 };
00885 
00886 class __EXPORT charmem : public CharacterProtocol
00887 {
00888 protected:
00889     char *buffer;
00890     size_t inp, out, size;
00891     bool dynamic;
00892 
00893     int _getch(void);
00894     int _putch(int code);
00895 
00896 public:
00897     charmem(char *mem, size_t size);
00898     charmem(size_t size);
00899     charmem();
00900     virtual ~charmem();
00901 
00902     void release(void);
00903 
00904     void set(char *mem, size_t size);
00905 
00906     void set(size_t size);
00907 
00908     inline void reset(void)
00909         {inp = out = 0;}
00910 
00911     inline void rewind(void)
00912         {inp = 0;}
00913 };
00914 
00915 class __EXPORT chartext : public CharacterProtocol
00916 {
00917 private:
00918     char *pos;
00919     size_t max;
00920 
00921     int _putch(int code);
00922     int _getch(void);
00923 
00924 public:
00925     chartext();
00926     chartext(char *buf);
00927     chartext(char *buf, size_t size);
00928     virtual ~chartext();
00929 };
00930 
00942 class __EXPORT keyassoc : protected mempager
00943 {
00944 private:
00948     class __LOCAL keydata : public NamedObject
00949     {
00950     public:
00951         void *data;
00952         char text[8];
00953 
00954         keydata(keyassoc *assoc, const char *id, unsigned max, unsigned bufsize);
00955     };
00956 
00957     friend class keydata;
00958 
00959     unsigned keycount;
00960     unsigned paths;
00961     size_t keysize;
00962     NamedObject **root;
00963     LinkedObject **list;
00964 
00965 protected:
00972     void *allocate(const char *name, size_t size);
00973 
00974 public:
00981     keyassoc(unsigned indexing = 177, size_t max = 0, size_t page = 0);
00982 
00986     ~keyassoc();
00987 
00992     inline unsigned count(void) const
00993         {return keycount;}
00994 
01000     inline void *operator()(const char *name)
01001         {return locate(name);}
01002 
01006     void purge(void);
01007 
01013     void *locate(const char *name);
01014 
01022     bool assign(const char *name, void *pointer);
01023 
01030     bool create(const char *name, void *pointer);
01031 
01038     void *remove(const char *name);
01039 };
01040 
01041 template <class T, size_t P = 0>
01042 class listof : private ObjectPager
01043 {
01044 public:
01045     inline listof() : ObjectPager(sizeof(T), P) {}
01046 
01047     inline T& operator[](unsigned item) const
01048         {return (T&)ObjectPager::get(item);}
01049 
01050     inline T* operator()(unsigned item) const
01051         {return (T*)ObjectPager::get(item);}
01052 
01053     inline const T& at(unsigned item) const
01054         {return (const T&)ObjectPager::get(item);}
01055 
01056     inline T* pull(void)
01057         {return (T*)ObjectPager::pull();}
01058 
01059     inline T* pop(void)
01060         {return (T*)ObjectPager::pop();}
01061 
01062     inline operator T**()
01063         {return (T**)ObjectPager::list();}
01064 
01065     inline T** list(void)
01066         {return (T**)ObjectPager::list();}
01067 
01068     inline T* operator++(void)
01069         {T* tmp = ObjectPager::add(); if(tmp) new((caddr_t)tmp) T; return tmp;}
01070 
01071     inline T* add(const T& object)
01072         {T* tmp = ObjectPager::add(); if(tmp) new((caddr_t)tmp) T(object); return tmp;}
01073 
01074     inline T* push(const T& object)
01075         {T* tmp = ObjectPager::push(); if(tmp) new((caddr_t)tmp) T(object); return tmp;}
01076 
01077     inline listof& operator<<(const T& object)
01078         {T* tmp = ObjectPager::add(); if(tmp) new((caddr_t)tmp) T(object); return *this;}
01079 
01080     inline listof& operator>>(const T& object)
01081         {T* tmp = ObjectPager::push(); if(tmp) new((caddr_t)tmp) T(object); return *this;}
01082 
01083 };
01084 
01085 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0>
01086 class mapof : private keyassoc
01087 {
01088 public:
01092     inline mapof() : keyassoc(I, M, P) {}
01093 
01098     inline unsigned count(void) const
01099         {return keyassoc::count();}
01100 
01104     inline void purge(void)
01105         {keyassoc::purge();}
01106 
01112     inline T *locate(const char *name)
01113         {return static_cast<T*>(keyassoc::locate(name));}
01114 
01115     inline T *operator[](const char *name)
01116         {return static_cast<T*>(keyassoc::locate(name));}
01117 
01123     inline T *operator()(const char *name)
01124         {return locate(name);}
01125 
01130     inline T *map(const char *name)
01131         {T *tmp = keyassoc::allocate(name, sizeof(T)); if(tmp) new((caddr_t)tmp) T;}
01132 
01138     inline void unmap(const char *name)
01139         {keyassoc::remove(name);}
01140 
01146     inline unsigned utilization(void) const
01147         {return mempager::utilization();}
01148 
01155     inline unsigned pages(void) const
01156         {return mempager::pages();}
01157 };
01158 
01166 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0>
01167 class assoc_pointer : private keyassoc
01168 {
01169 public:
01173     inline assoc_pointer() : keyassoc(I, M, P) {}
01174 
01179     inline unsigned count(void) const
01180         {return keyassoc::count();}
01181 
01185     inline void purge(void)
01186         {keyassoc::purge();}
01187 
01193     inline T *locate(const char *name)
01194         {return static_cast<T*>(keyassoc::locate(name));}
01195 
01196     inline T *operator[](const char *name)
01197         {return static_cast<T*>(keyassoc::locate(name));}
01198 
01199 
01205     inline T *operator()(const char *name)
01206         {return locate(name);}
01207 
01215     inline bool assign(char *name, T *pointer)
01216         {return keyassoc::assign(name, pointer);}
01217 
01224     inline bool create(char *name, T *pointer)
01225         {return keyassoc::create(name, pointer);}
01226 
01232     inline void remove(char *name)
01233         {keyassoc::remove(name);}
01234 
01240     inline unsigned utilization(void) const
01241         {return mempager::utilization();}
01242 
01249     inline unsigned pages(void) const
01250         {return mempager::pages();}
01251 };
01252 
01259 template <typename T>
01260 class pager : private MemoryRedirect, private PagerPool
01261 {
01262 public:
01267     inline pager(mempager *heap = NULL) : MemoryRedirect(heap), PagerPool() {}
01268 
01273     inline T *operator()(void)
01274         {return new(get(sizeof(T))) T;}
01275 
01280     inline T *operator*()
01281         {return new(get(sizeof(T))) T;}
01282 };
01283 
01289 template <class T, unsigned M = 177>
01290 class keypager : public mempager
01291 {
01292 private:
01293     NamedObject *idx[M];
01294 
01295 public:
01300     inline keypager(size_t size) : mempager(size) {}
01301 
01305     inline ~keypager()
01306         {NamedObject::purge(idx, M); mempager::purge();}
01307 
01314     inline T *get(const char *name) const {
01315         T *node = (static_cast<T*>(NamedObject::map(idx, name, M)));
01316         if(!node) {
01317             node = init<T>(static_cast<T*>(mempager::_alloc(sizeof(T))));
01318             node->NamedObject::add(idx, name, M);
01319         }
01320         return node;
01321     }
01322 
01328     bool test(const char *name) const
01329         {return NamedObject::map(idx, name, M) != NULL;}
01330 
01337     inline T *operator[](const char *name) const
01338         {return get(name);}
01339 
01344     inline T *begin(void) const
01345         {return static_cast<T*>(NamedObject::skip(idx, NULL, M));}
01346 
01352     inline T *next(T *current) const
01353         {return static_cast<T*>(NamedObject::skip(idx, current, M));}
01354 
01359     inline unsigned count(void) const
01360         {return NamedObject::count(idx, M);}
01361 
01368     inline T **index(void) const
01369         {return NamedObject::index(idx, M);}
01370 
01377     inline T **sort(void) const
01378         {return NamedObject::sort(NamedObject::index(idx, M));}
01379 
01383     typedef linked_pointer<T> iterator;
01384 };
01385 
01389 typedef StringPager stringlist_t;
01390 
01394 typedef StringPager::member stringlistitem_t;
01395 
01399 typedef DirPager dirlist_t;
01400 
01401 inline const char *shift(stringlist_t& list)
01402     {return list.pull();}
01403 
01404 inline void unshift(stringlist_t& list, const char *text)
01405     {list.push(text);}
01406 
01407 
01408 inline String str(StringPager& list, const char *prefix = NULL, const char *middle = NULL, const char *suffix = NULL)
01409     {return list.join(prefix, middle, suffix);}
01410 
01411 } // namespace ucommon
01412 
01413 #endif