ucommon
|
00001 // Copyright (C) 2006-2014 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 } // namespace ucommon 01411 01412 #endif