UCommon
|
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