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