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 public: 00258 member(LinkedObject **root, const char *data); 00259 inline const char *operator*() 00260 {return text;}; 00261 00262 inline const char *get(void) 00263 {return text;}; 00264 }; 00265 00270 stringpager(size_t pagesize = 256); 00271 00276 inline unsigned count(void) 00277 {return members;}; 00278 00285 const char *get(unsigned item); 00286 00291 void add(const char *text); 00292 00298 void add(char **list); 00299 00304 void clear(void); 00305 00312 inline const char *operator[](unsigned item) 00313 {return get(item);}; 00314 00320 inline stringpager::member *begin(void) 00321 {return static_cast<stringpager::member *>(root);}; 00322 00327 inline void operator+=(const char *text) 00328 {add(text);}; 00329 00334 inline stringpager& operator<<(const char *text) 00335 {add(text); return *this;}; 00336 }; 00337 00342 class __EXPORT bufpager : public memalloc, public CharacterProtocol 00343 { 00344 private: 00345 typedef struct cpage { 00346 struct cpage *next; 00347 char *text; 00348 unsigned size, used; 00349 } cpage_t; 00350 00351 cpage_t *first, *last, *current, *freelist; 00352 unsigned cpos; 00353 unsigned long ccount; 00354 00355 virtual int _getch(void); 00356 virtual int _putch(int code); 00357 00358 protected: 00359 virtual void *_alloc(size_t size); 00360 00361 public: 00365 void reset(void); 00366 00370 void rewind(void); 00371 00376 inline unsigned long getUsed(void) 00377 {return ccount;}; 00378 00379 bufpager(size_t page = 0); 00380 }; 00381 00389 class __EXPORT autorelease 00390 { 00391 private: 00392 LinkedObject *pool; 00393 00394 public: 00398 autorelease(); 00399 00403 ~autorelease(); 00404 00410 void release(void); 00411 00416 void operator+=(LinkedObject *object); 00417 }; 00418 00429 class __EXPORT PagerObject : public LinkedObject, public CountedObject 00430 { 00431 protected: 00432 friend class PagerPool; 00433 00434 PagerPool *pager; 00435 00439 PagerObject(); 00440 00444 void release(void); 00445 00449 void dealloc(void); 00450 }; 00451 00460 class __EXPORT PagerPool : public MemoryProtocol 00461 { 00462 private: 00463 LinkedObject *freelist; 00464 pthread_mutex_t mutex; 00465 00466 protected: 00467 PagerPool(); 00468 virtual ~PagerPool(); 00469 00470 PagerObject *get(size_t size); 00471 00472 public: 00477 void put(PagerObject *object); 00478 }; 00479 00480 class __EXPORT charmem : public CharacterProtocol 00481 { 00482 protected: 00483 char *buffer; 00484 size_t inp, out, size; 00485 bool dynamic; 00486 00487 int _getch(void); 00488 int _putch(int code); 00489 00490 public: 00491 charmem(char *mem, size_t size); 00492 charmem(size_t size); 00493 charmem(); 00494 virtual ~charmem(); 00495 00496 void release(void); 00497 00498 void set(char *mem, size_t size); 00499 00500 void set(size_t size); 00501 00502 inline void reset(void) 00503 {inp = out = 0;} 00504 00505 inline void rewind(void) 00506 {inp = 0;} 00507 }; 00508 00509 class __EXPORT chartext : public CharacterProtocol 00510 { 00511 private: 00512 char *pos; 00513 size_t max; 00514 00515 int _putch(int code); 00516 int _getch(void); 00517 00518 public: 00519 chartext(); 00520 chartext(char *buf); 00521 chartext(char *buf, size_t size); 00522 virtual ~chartext(); 00523 }; 00524 00536 class __EXPORT keyassoc : protected mempager 00537 { 00538 private: 00542 class __LOCAL keydata : public NamedObject 00543 { 00544 public: 00545 void *data; 00546 char text[8]; 00547 00548 keydata(keyassoc *assoc, char *id, unsigned max, unsigned bufsize); 00549 }; 00550 00551 friend class keydata; 00552 00553 unsigned count; 00554 unsigned paths; 00555 size_t keysize; 00556 NamedObject **root; 00557 LinkedObject **list; 00558 00559 public: 00566 keyassoc(unsigned indexing = 177, size_t max = 0, size_t page = 0); 00567 00571 ~keyassoc(); 00572 00577 inline unsigned getCount(void) 00578 {return count;}; 00579 00585 inline void *operator()(const char *name) 00586 {return locate(name);}; 00587 00591 void purge(void); 00592 00598 void *locate(const char *name); 00599 00607 bool assign(char *name, void *pointer); 00608 00615 bool create(char *name, void *pointer); 00616 00623 void *remove(const char *name); 00624 }; 00625 00633 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0> 00634 class assoc_pointer : private keyassoc 00635 { 00636 public: 00640 inline assoc_pointer() : keyassoc(I, M, P) {}; 00641 00646 inline unsigned getCount(void) 00647 {return keyassoc::getCount();}; 00648 00652 inline void purge(void) 00653 {keyassoc::purge();}; 00654 00660 inline T *locate(const char *name) 00661 {return static_cast<T*>(keyassoc::locate(name));}; 00662 00668 inline T *operator()(const char *name) 00669 {return locate(name);}; 00670 00678 inline bool assign(char *name, T *pointer) 00679 {return keyassoc::assign(name, pointer);}; 00680 00687 inline bool create(char *name, T *pointer) 00688 {return keyassoc::create(name, pointer);}; 00689 00695 inline void remove(char *name) 00696 {keyassoc::remove(name);}; 00697 00703 inline unsigned utilization(void) 00704 {return mempager::utilization();}; 00705 00712 inline unsigned getPages(void) 00713 {return mempager::getPages();}; 00714 }; 00715 00722 template <typename T> 00723 class pager : private MemoryRedirect, private PagerPool 00724 { 00725 public: 00730 inline pager(mempager *heap = NULL) : MemoryRedirect(heap), PagerPool() {}; 00731 00735 inline ~pager() 00736 {mempager::purge();}; 00737 00742 inline T *operator()(void) 00743 {return new(get(sizeof(T))) T;}; 00744 00749 inline T *operator*() 00750 {return new(get(sizeof(T))) T;}; 00751 }; 00752 00758 template <class T, unsigned M = 177> 00759 class keypager : public mempager 00760 { 00761 private: 00762 NamedObject *idx[M]; 00763 00764 public: 00769 inline keypager(size_t size) : mempager(size) {}; 00770 00774 inline ~keypager() 00775 {NamedObject::purge(idx, M); mempager::purge();}; 00776 00783 inline T *get(const char *name) const { 00784 T *node = (static_cast<T*>(NamedObject::map(idx, name, M))); 00785 if(!node) { 00786 node = init<T>(static_cast<T*>(mempager::_alloc(sizeof(T)))); 00787 node->NamedObject::add(idx, name, M); 00788 } 00789 return node; 00790 } 00791 00797 bool test(const char *name) const 00798 {return NamedObject::map(idx, name, M) != NULL;}; 00799 00806 inline T *operator[](const char *name) const 00807 {return get(name);}; 00808 00813 inline T *begin(void) const 00814 {return static_cast<T*>(NamedObject::skip(idx, NULL, M));}; 00815 00821 inline T *next(T *current) const 00822 {return static_cast<T*>(NamedObject::skip(idx, current, M));}; 00823 00828 inline unsigned count(void) const 00829 {return NamedObject::count(idx, M);}; 00830 00837 inline T **index(void) const 00838 {return NamedObject::index(idx, M);}; 00839 00846 inline T **sort(void) const 00847 {return NamedObject::sort(NamedObject::index(idx, M));}; 00848 }; 00849 00850 END_NAMESPACE 00851 00852 #endif