UCommon
memory.h
Go to the documentation of this file.
1 // Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
2 //
3 // This file is part of GNU uCommon C++.
4 //
5 // GNU uCommon C++ is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // GNU uCommon C++ is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17 
30 #ifndef _UCOMMON_MEMORY_H_
31 #define _UCOMMON_MEMORY_H_
32 
33 #ifndef _UCOMMON_CONFIG_H_
34 #include <ucommon/platform.h>
35 #endif
36 
37 #ifndef _UCOMMON_PROTOCOLS_H_
38 #include <ucommon/protocols.h>
39 #endif
40 
41 #ifndef _UCOMMON_LINKED_H_
42 #include <ucommon/linked.h>
43 #endif
44 
45 #ifndef _UCOMMON_STRING_H_
46 #include <ucommon/string.h>
47 #endif
48 
49 NAMESPACE_UCOMMON
50 
51 class PagerPool;
52 
60 class __EXPORT memalloc : public MemoryProtocol, protected LockingProtocol
61 {
62 private:
63  friend class bufpager;
64 
65  size_t pagesize, align;
66  unsigned count;
67 
68  typedef struct mempage {
69  struct mempage *next;
70  union {
71  void *memalign;
72  unsigned used;
73  };
74  } page_t;
75 
76  page_t *page;
77 
78 protected:
79  unsigned limit;
80 
85  page_t *pager(void);
86 
87 public:
92  memalloc(size_t page = 0);
93 
97  virtual ~memalloc();
98 
103  inline unsigned getPages(void)
104  {return count;};
105 
113  inline unsigned getLimit(void)
114  {return limit;};
115 
120  inline unsigned getAlloc(void)
121  {return pagesize;};
122 
133  unsigned utilization(void);
134 
138  void purge(void);
139 
147  virtual void *_alloc(size_t size);
148 };
149 
170 class __EXPORT mempager : public memalloc
171 {
172 private:
173  pthread_mutex_t mutex;
174 
175 protected:
182  virtual void _lock(void);
183 
187  virtual void _unlock(void);
188 
189 public:
194  mempager(size_t page = 0);
195 
199  virtual ~mempager();
200 
211  unsigned utilization(void);
212 
216  void purge(void);
217 
225  virtual void dealloc(void *memory);
226 
235  virtual void *_alloc(size_t size);
236 };
237 
238 class __EXPORT objectpager : protected memalloc
239 {
240 public:
241  class __EXPORT member : public LinkedObject
242  {
243  private:
244  void *mem;
245 
246  protected:
247  friend class objectpager;
248 
249  inline void set(member *node)
250  {next = node;};
251 
252  member(LinkedObject **root);
253  member();
254 
255  public:
256  inline void *operator*() const
257  {return mem;};
258 
259  inline void *get(void) const
260  {return mem;};
261  };
262 
263 private:
264  unsigned members;
265  LinkedObject *root;
266  size_t typesize;
267  member *last;
268  void **index;
269 
270 protected:
271  objectpager(size_t objsize, size_t pagesize = 256);
272 
279  void *get(unsigned item);
280 
285  void *add(void);
286 
287  void *push(void);
288 
293  void *pull(void);
294 
299  void *pop(void);
300 
301 public:
306  void clear(void);
307 
313  inline objectpager::member *begin(void)
314  {return static_cast<objectpager::member *>(root);};
315 
316  inline operator bool()
317  {return members > 0;}
318 
319  inline bool operator!()
320  {return !members;}
321 
326  inline unsigned count(void)
327  {return members;};
328 
329 protected:
334  void **list(void);
335 };
336 
342 class __EXPORT stringpager : protected memalloc
343 {
344 private:
345  unsigned members;
346  LinkedObject *root;
347 
348 public:
355  class __EXPORT member : public LinkedObject
356  {
357  private:
358  const char *text;
359 
360  protected:
361  friend class stringpager;
362 
363  inline void set(member *node)
364  {next = node;};
365 
366  member(LinkedObject **root, const char *data);
367  member(const char *data);
368 
369  public:
370  inline const char *operator*() const
371  {return text;};
372 
373  inline const char *get(void) const
374  {return text;};
375  };
376 
381  stringpager(size_t pagesize = 256);
382 
383  stringpager(char **list, size_t pagesize = 256);
384 
389  inline unsigned count(void)
390  {return members;};
391 
398  const char *get(unsigned item);
399 
405  void set(unsigned item, const char *string);
406 
411  void add(const char *text);
412 
417  void push(const char *text);
418 
423  void push(char **text);
424 
429  const char *pull(void);
430 
435  const char *pop(void);
436 
442  void add(char **list);
443 
449  void set(char **list);
450 
455  void clear(void);
456 
463  inline const char *operator[](unsigned item)
464  {return get(item);};
465 
471  inline stringpager::member *begin(void)
472  {return static_cast<stringpager::member *>(root);};
473 
478  inline void operator+=(const char *text)
479  {add(text);};
480 
485  inline stringpager& operator<<(const char *text)
486  {add(text); return *this;}
487 
488  inline stringpager& operator>>(const char *text)
489  {push(text); return *this;}
490 
494  void sort(void);
495 
500  char **list(void);
501 
510  unsigned token(const char *text, const char *list, const char *quote = NULL, const char *end = NULL);
511 
512  unsigned split(const char *text, const char *string, unsigned flags = 0);
513 
514  unsigned split(stringex_t& expr, const char *string, unsigned flags = 0);
515 
516  String join(const char *prefix = NULL, const char *middle = NULL, const char *suffix = NULL);
517 
518  inline operator bool()
519  {return members > 0;}
520 
521  inline bool operator!()
522  {return !members;}
523 
524  inline stringpager& operator=(char **list)
525  {set(list); return *this;}
526 
527  inline const char *operator*()
528  {return pull();}
529 
530  inline operator char **()
531  {return list();};
532 
533 private:
534  member *last;
535  char **index;
536 };
537 
545 class __EXPORT DirPager : protected stringpager
546 {
547 protected:
548  const char *dir;
549 
555  virtual bool filter(const char *filename);
556 
562  bool load(const char *path);
563 
564 public:
565  DirPager();
566 
567  DirPager(const char *path);
568 
569  void operator=(const char *path);
570 
571  inline const char *operator*()
572  {return dir;};
573 
574  inline operator bool()
575  {return dir != NULL;};
576 
577  inline bool operator!()
578  {return dir == NULL;};
579 
586  inline const char *operator[](unsigned item)
587  {return stringpager::get(item);};
588 
589  inline const char *get(unsigned item)
590  {return stringpager::get(item);};
591 };
592 
597 class __EXPORT bufpager : public memalloc, public CharacterProtocol
598 {
599 private:
600  typedef struct cpage {
601  struct cpage *next;
602  char *text;
603  unsigned size, used;
604  } cpage_t;
605 
606  cpage_t *first, *last, *current, *freelist;
607  unsigned cpos;
608  unsigned long ccount;
609 
610  virtual int _getch(void);
611  virtual int _putch(int code);
612 
613 protected:
614  virtual void *_alloc(size_t size);
615 
616 public:
620  void reset(void);
621 
625  void rewind(void);
626 
631  char *dup(void);
632 
637  void set(const char *text);
638 
643  void add(const char *text);
644 
651  size_t get(char *text, size_t size);
652 
658  void put(const char *text, size_t size);
659 
664  inline unsigned long getUsed(void)
665  {return ccount;}
666 
671  inline char *operator *()
672  {return dup();}
673 
678  inline bufpager& operator<<(const char *text)
679  {add(text); return *this;};
680 
681  bufpager(size_t page = 0);
682 
683  char *request(size_t *iosize);
684 
685  char *copy(size_t *iosize);
686 
687  void release(void);
688 
689  void commit(size_t size);
690 };
691 
699 class __EXPORT autorelease
700 {
701 private:
702  LinkedObject *pool;
703 
704 public:
708  autorelease();
709 
713  ~autorelease();
714 
720  void release(void);
721 
726  void operator+=(LinkedObject *object);
727 };
728 
739 class __EXPORT PagerObject : public LinkedObject, public CountedObject
740 {
741 protected:
742  friend class PagerPool;
743 
744  PagerPool *pager;
745 
749  PagerObject();
750 
754  void release(void);
755 
759  void dealloc(void);
760 };
761 
770 class __EXPORT PagerPool : public MemoryProtocol
771 {
772 private:
773  LinkedObject *freelist;
774  pthread_mutex_t mutex;
775 
776 protected:
777  PagerPool();
778  virtual ~PagerPool();
779 
780  PagerObject *get(size_t size);
781 
782 public:
787  void put(PagerObject *object);
788 };
789 
790 class __EXPORT charmem : public CharacterProtocol
791 {
792 protected:
793  char *buffer;
794  size_t inp, out, size;
795  bool dynamic;
796 
797  int _getch(void);
798  int _putch(int code);
799 
800 public:
801  charmem(char *mem, size_t size);
802  charmem(size_t size);
803  charmem();
804  virtual ~charmem();
805 
806  void release(void);
807 
808  void set(char *mem, size_t size);
809 
810  void set(size_t size);
811 
812  inline void reset(void)
813  {inp = out = 0;}
814 
815  inline void rewind(void)
816  {inp = 0;}
817 };
818 
819 class __EXPORT chartext : public CharacterProtocol
820 {
821 private:
822  char *pos;
823  size_t max;
824 
825  int _putch(int code);
826  int _getch(void);
827 
828 public:
829  chartext();
830  chartext(char *buf);
831  chartext(char *buf, size_t size);
832  virtual ~chartext();
833 };
834 
846 class __EXPORT keyassoc : protected mempager
847 {
848 private:
852  class __LOCAL keydata : public NamedObject
853  {
854  public:
855  void *data;
856  char text[8];
857 
858  keydata(keyassoc *assoc, char *id, unsigned max, unsigned bufsize);
859  };
860 
861  friend class keydata;
862 
863  unsigned count;
864  unsigned paths;
865  size_t keysize;
866  NamedObject **root;
867  LinkedObject **list;
868 
869 protected:
876  void *allocate(char *name, size_t size);
877 
878 public:
885  keyassoc(unsigned indexing = 177, size_t max = 0, size_t page = 0);
886 
890  ~keyassoc();
891 
896  inline unsigned getCount(void)
897  {return count;};
898 
904  inline void *operator()(const char *name)
905  {return locate(name);};
906 
910  void purge(void);
911 
917  void *locate(const char *name);
918 
926  bool assign(char *name, void *pointer);
927 
934  bool create(char *name, void *pointer);
935 
942  void *remove(const char *name);
943 };
944 
945 template <class T, size_t P = 0>
946 class listof : private objectpager
947 {
948 public:
949  inline listof() : objectpager(sizeof(T), P) {};
950 
951  inline T& operator[](unsigned item) const
952  {return (T&)objectpager::get(item);}
953 
954  inline T* operator()(unsigned item) const
955  {return (T*)objectpager::get(item);}
956 
957  inline T* get(unsigned item) const
958  {return (T*)objectpager::get(item);}
959 
960  inline T* pull(void)
961  {return (T*)objectpager::pull();}
962 
963  inline T* pop(void)
964  {return (T*)objectpager::pop();}
965 
966  inline operator T**()
967  {return (T**)objectpager::list();}
968 
969  inline T** list(void)
970  {return (T**)objectpager::list();}
971 
972  inline T* operator++(void)
973  {T* tmp = objectpager::add(); if(tmp) new((caddr_t)tmp) T; return tmp;}
974 
975  inline T* add(const T& object)
976  {T* tmp = objectpager::add(); if(tmp) new((caddr_t)tmp) T(object); return tmp;}
977 
978  inline T* push(const T& object)
979  {T* tmp = objectpager::push(); if(tmp) new((caddr_t)tmp) T(object); return tmp;}
980 
981  inline listof& operator<<(const T& object)
982  {T* tmp = objectpager::add(); if(tmp) new((caddr_t)tmp) T(object); return *this;}
983 
984  inline listof& operator>>(const T& object)
985  {T* tmp = objectpager::push(); if(tmp) new((caddr_t)tmp) T(object); return *this;}
986 
987 };
988 
989 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0>
990 class mapof : private keyassoc
991 {
992 public:
996  inline mapof() : keyassoc(I, M, P) {};
997 
1002  inline unsigned getCount(void)
1003  {return keyassoc::getCount();};
1004 
1008  inline void purge(void)
1009  {keyassoc::purge();};
1010 
1016  inline T *locate(const char *name)
1017  {return static_cast<T*>(keyassoc::locate(name));}
1018 
1019  inline T *operator[](const char *name)
1020  {return static_cast<T*>(keyassoc::locate(name));}
1021 
1027  inline T *operator()(const char *name)
1028  {return locate(name);};
1029 
1034  inline T *map(char *name)
1035  {T *tmp = keyassoc::allocate(name, sizeof(T)); if(tmp) new((caddr_t)tmp) T;}
1036 
1042  inline void unmap(char *name)
1043  {keyassoc::remove(name);};
1044 
1050  inline unsigned utilization(void)
1051  {return mempager::utilization();};
1052 
1059  inline unsigned getPages(void)
1060  {return mempager::getPages();};
1061 };
1062 
1070 template <class T, unsigned I = 177, size_t M = 0, size_t P = 0>
1071 class assoc_pointer : private keyassoc
1072 {
1073 public:
1077  inline assoc_pointer() : keyassoc(I, M, P) {};
1078 
1083  inline unsigned getCount(void)
1084  {return keyassoc::getCount();}
1085 
1089  inline void purge(void)
1090  {keyassoc::purge();}
1091 
1097  inline T *locate(const char *name)
1098  {return static_cast<T*>(keyassoc::locate(name));}
1099 
1100  inline T *operator[](const char *name)
1101  {return static_cast<T*>(keyassoc::locate(name));}
1102 
1103 
1109  inline T *operator()(const char *name)
1110  {return locate(name);}
1111 
1119  inline bool assign(char *name, T *pointer)
1120  {return keyassoc::assign(name, pointer);}
1121 
1128  inline bool create(char *name, T *pointer)
1129  {return keyassoc::create(name, pointer);}
1130 
1136  inline void remove(char *name)
1137  {keyassoc::remove(name);}
1138 
1144  inline unsigned utilization(void)
1145  {return mempager::utilization();}
1146 
1153  inline unsigned getPages(void)
1154  {return mempager::getPages();}
1155 };
1156 
1163 template <typename T>
1164 class pager : private MemoryRedirect, private PagerPool
1165 {
1166 public:
1171  inline pager(mempager *heap = NULL) : MemoryRedirect(heap), PagerPool() {};
1172 
1176  inline ~pager()
1177  {mempager::purge();};
1178 
1183  inline T *operator()(void)
1184  {return new(get(sizeof(T))) T;};
1185 
1190  inline T *operator*()
1191  {return new(get(sizeof(T))) T;};
1192 };
1193 
1199 template <class T, unsigned M = 177>
1200 class keypager : public mempager
1201 {
1202 private:
1203  NamedObject *idx[M];
1204 
1205 public:
1210  inline keypager(size_t size) : mempager(size) {};
1211 
1215  inline ~keypager()
1216  {NamedObject::purge(idx, M); mempager::purge();};
1217 
1224  inline T *get(const char *name) const {
1225  T *node = (static_cast<T*>(NamedObject::map(idx, name, M)));
1226  if(!node) {
1227  node = init<T>(static_cast<T*>(mempager::_alloc(sizeof(T))));
1228  node->NamedObject::add(idx, name, M);
1229  }
1230  return node;
1231  }
1232 
1238  bool test(const char *name) const
1239  {return NamedObject::map(idx, name, M) != NULL;};
1240 
1247  inline T *operator[](const char *name) const
1248  {return get(name);};
1249 
1254  inline T *begin(void) const
1255  {return static_cast<T*>(NamedObject::skip(idx, NULL, M));};
1256 
1262  inline T *next(T *current) const
1263  {return static_cast<T*>(NamedObject::skip(idx, current, M));};
1264 
1269  inline unsigned count(void) const
1270  {return NamedObject::count(idx, M);};
1271 
1278  inline T **index(void) const
1279  {return NamedObject::index(idx, M);};
1280 
1287  inline T **sort(void) const
1288  {return NamedObject::sort(NamedObject::index(idx, M));};
1289 };
1290 
1295 
1300 
1305 
1306 inline const char *shift(stringlist_t& list)
1307  {return list.pull();}
1308 
1309 inline void unshift(stringlist_t& list, const char *text)
1310  {list.push(text);}
1311 
1312 
1313 inline String str(stringpager& list, const char *prefix = NULL, const char *middle = NULL, const char *suffix = NULL)
1314  {return list.join(prefix, middle, suffix);}
1315 
1316 END_NAMESPACE
1317 
1318 #endif