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 00238 class __EXPORT bufpager : public memalloc, public CharacterProtocol 00239 { 00240 private: 00241 typedef struct cpage { 00242 struct cpage *next; 00243 char *text; 00244 unsigned size, used; 00245 } cpage_t; 00246 00247 cpage_t *first, *last, *current, *freelist; 00248 unsigned cpos; 00249 unsigned long ccount; 00250 00251 virtual int _getch(void); 00252 virtual int _putch(int code); 00253 00254 protected: 00255 virtual void *_alloc(size_t size); 00256 00257 public: 00261 void reset(void); 00262 00266 void rewind(void); 00267 00272 inline unsigned long getUsed(void) 00273 {return ccount;}; 00274 00275 bufpager(size_t page = 0); 00276 }; 00277 00285 class __EXPORT autorelease 00286 { 00287 private: 00288 LinkedObject *pool; 00289 00290 public: 00294 autorelease(); 00295 00299 ~autorelease(); 00300 00306 void release(void); 00307 00312 void operator+=(LinkedObject *object); 00313 }; 00314 00325 class __EXPORT PagerObject : public LinkedObject, public CountedObject 00326 { 00327 protected: 00328 friend class PagerPool; 00329 00330 PagerPool *pager; 00331 00335 PagerObject(); 00336 00340 void release(void); 00341 00345 void dealloc(void); 00346 }; 00347 00356 class __EXPORT PagerPool : public MemoryProtocol 00357 { 00358 private: 00359 LinkedObject *freelist; 00360 pthread_mutex_t mutex; 00361 00362 protected: 00363 PagerPool(); 00364 ~PagerPool(); 00365 00366 PagerObject *get(size_t size); 00367 00368 public: 00373 void put(PagerObject *object); 00374 }; 00375 00376 class __EXPORT charmem : public CharacterProtocol 00377 { 00378 protected: 00379 char *buffer; 00380 size_t inp, out, size; 00381 bool dynamic; 00382 00383 int _getch(void); 00384 int _putch(int code); 00385 00386 public: 00387 charmem(char *mem, size_t size); 00388 charmem(size_t size); 00389 charmem(); 00390 ~charmem(); 00391 00392 void release(void); 00393 00394 void set(char *mem, size_t size); 00395 00396 void set(size_t size); 00397 00398 inline void reset(void) 00399 {inp = out = 0;} 00400 00401 inline void rewind(void) 00402 {inp = 0;} 00403 }; 00404 00405 class __EXPORT chartext : public CharacterProtocol 00406 { 00407 private: 00408 char *pos; 00409 size_t max; 00410 00411 int _putch(int code); 00412 int _getch(void); 00413 00414 public: 00415 chartext(); 00416 chartext(char *buf); 00417 chartext(char *buf, size_t size); 00418 }; 00419 00431 class __EXPORT keyassoc : protected mempager 00432 { 00433 private: 00437 class __LOCAL keydata : public NamedObject 00438 { 00439 public: 00440 void *data; 00441 char text[8]; 00442 00443 keydata(keyassoc *assoc, char *id, unsigned max, unsigned bufsize); 00444 }; 00445 00446 friend class keydata; 00447 00448 unsigned count; 00449 unsigned paths; 00450 size_t keysize; 00451 NamedObject **root; 00452 LinkedObject **list; 00453 00454 public: 00461 keyassoc(unsigned indexing = 177, size_t max = 0, size_t page = 0); 00462 00466 ~keyassoc(); 00467 00472 inline unsigned getCount(void) 00473 {return count;}; 00474 00480 inline void *operator()(const char *name) 00481 {return locate(name);}; 00482 00486 void purge(void); 00487 00493 void *locate(const char *name); 00494 00502 bool assign(char *name, void *pointer); 00503 00510 bool create(char *name, void *pointer); 00511 00518 void *remove(const char *name); 00519 }; 00520 00528 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0> 00529 class assoc_pointer : private keyassoc 00530 { 00531 public: 00535 inline assoc_pointer() : keyassoc(I, M, P) {}; 00536 00541 inline unsigned getCount(void) 00542 {return keyassoc::getCount();}; 00543 00547 inline void purge(void) 00548 {keyassoc::purge();}; 00549 00555 inline T *locate(const char *name) 00556 {return static_cast<T*>(keyassoc::locate(name));}; 00557 00563 inline T *operator()(const char *name) 00564 {return locate(name);}; 00565 00573 inline bool assign(char *name, T *pointer) 00574 {return keyassoc::assign(name, pointer);}; 00575 00582 inline bool create(char *name, T *pointer) 00583 {return keyassoc::create(name, pointer);}; 00584 00590 inline void remove(char *name) 00591 {keyassoc::remove(name);}; 00592 00598 inline unsigned utilization(void) 00599 {return mempager::utilization();}; 00600 00607 inline unsigned getPages(void) 00608 {return mempager::getPages();}; 00609 }; 00610 00617 template <typename T> 00618 class pager : private MemoryRedirect, private PagerPool 00619 { 00620 public: 00625 inline pager(mempager *heap = NULL) : MemoryRedirect(heap), PagerPool() {}; 00626 00630 inline ~pager() 00631 {mempager::purge();}; 00632 00637 inline T *operator()(void) 00638 {return new(get(sizeof(T))) T;}; 00639 00644 inline T *operator*() 00645 {return new(get(sizeof(T))) T;}; 00646 }; 00647 00653 template <class T, unsigned M = 177> 00654 class keypager : public mempager 00655 { 00656 private: 00657 NamedObject *idx[M]; 00658 00659 public: 00664 inline keypager(size_t size) : mempager(size) {}; 00665 00669 inline ~keypager() 00670 {NamedObject::purge(idx, M); mempager::purge();}; 00671 00678 inline T *get(const char *name) const { 00679 T *node = (static_cast<T*>(NamedObject::map(idx, name, M))); 00680 if(!node) { 00681 node = init<T>(static_cast<T*>(mempager::_alloc(sizeof(T)))); 00682 node->NamedObject::add(idx, name, M); 00683 } 00684 return node; 00685 } 00686 00692 bool test(const char *name) const 00693 {return NamedObject::map(idx, name, M) != NULL;}; 00694 00701 inline T *operator[](const char *name) const 00702 {return get(name);}; 00703 00708 inline T *begin(void) const 00709 {return static_cast<T*>(NamedObject::skip(idx, NULL, M));}; 00710 00716 inline T *next(T *current) const 00717 {return static_cast<T*>(NamedObject::skip(idx, current, M));}; 00718 00723 inline unsigned count(void) const 00724 {return NamedObject::count(idx, M);}; 00725 00732 inline T **index(void) const 00733 {return NamedObject::index(idx, M);}; 00734 00741 inline T **sort(void) const 00742 {return NamedObject::sort(NamedObject::index(idx, M));}; 00743 }; 00744 00745 END_NAMESPACE 00746 00747 #endif