00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef FRAME_MEMORY_H
00017 #define FRAME_MEMORY_H
00018
00019 #include <sys/shm.h>
00020 #include <unistd.h>
00021 #include <map>
00022 #include "definitions.h"
00023 #include "frame_utils.h"
00024 #include "frame_mutex.h"
00025
00037
00038 const char MemPoolHeaderIdentifier[] = "MemPoolHeader";
00039
00042 class tAbstractMemoryPool {
00043 protected:
00045 bool _master;
00047 long _memsize;
00049 void* _memptr;
00050 public:
00051 tAbstractMemoryPool(bool master = false, const string keystr = "", long memsize = CFG_MemPoolStdSize);
00052 virtual ~tAbstractMemoryPool() {};
00053 virtual void getmem(void*& memptr, long& memsize) {memptr=_memptr; memsize=_memsize;};
00054 virtual char* getmembase() {return (char*)_memptr;};
00055 virtual long getmemsize() {return _memsize;};
00056 };
00057
00060 class tSharedMemoryPool : public tAbstractMemoryPool {
00062 int _shmid;
00063 public:
00064 tSharedMemoryPool(bool master = false, const string keystr = "", long size = CFG_MemPoolStdSize);
00065 virtual ~tSharedMemoryPool();
00066 };
00067
00068
00069 class tMemoryAllocator_LIFO_Iterator;
00070 class tMemoryAllocator_FIFO_Iterator;
00071
00074 class tMemoryAllocator {
00075 protected:
00076 typedef unsigned long offsettype;
00077
00079 struct tBlockHeader {
00080 struct {
00081 offsettype previous;
00082 offsettype next;
00083 } memoffset;
00084 struct {
00085 offsettype previous;
00086 offsettype next;
00087 } keyoffset;
00088 long key;
00089 int datasize;
00090 };
00091
00093 struct tMemPoolHeader {
00095 void* membase;
00097 char identifier[sizeof(MemPoolHeaderIdentifier)];
00098 struct {
00100 offsettype start;
00102 offsettype end;
00103 } mem;
00104 struct {
00106 offsettype head;
00108 offsettype tail;
00109 } blocks;
00110 struct {
00112 offsettype head;
00114 offsettype tail;
00115 } keys;
00116 };
00117
00119 bool _master;
00121 tAbstractMemoryPool* _mempool;
00123 tAbstractMutex* _mutex;
00124
00125 public:
00126
00128 struct tKeyHintStruc {
00129 tBlockHeader* first;
00130 tBlockHeader* last;
00131 bool used;
00132 };
00133
00135 class tKeyHint {
00136 tKeyHintStruc _data;
00137 public:
00138 tKeyHint() {_data.first=NULL; _data.last=NULL; _data.used=false;};
00139 tKeyHint(tKeyHintStruc keyhintstruc) : _data(keyhintstruc) {};
00140 tKeyHint(tBlockHeader* f, tBlockHeader* l) {_data.first=f; _data.last=l; _data.used=true;};
00141 void setfirst(tBlockHeader* first) {_data.first = first;};
00142 void setlast(tBlockHeader* last) {_data.last = last;};
00143 tBlockHeader* first() const {return _data.first;};
00144 tBlockHeader* last() const {return _data.last;};
00145 bool used() const {return _data.used;};
00146 tKeyHintStruc value() const {return _data;};
00147 };
00148
00150 class tBlock {
00151 public:
00152 tBlockHeader* header;
00153 void* data;
00154 long datasize;
00155 tBlock() : header(NULL), data(NULL), datasize(0) {};
00156 tBlock(tBlockHeader* _hdr, void* _data = NULL) : header(_hdr), data(_data) {
00157 if ((data!=NULL)&&(header==NULL)) header=(tBlockHeader*)((char*)data-sizeof(tBlockHeader));
00158 data=(header==NULL)?NULL:((char*)header+sizeof(tBlockHeader));
00159 datasize=(header==NULL)?0:header->datasize;
00160 }
00161 };
00162
00163 tMemoryAllocator(bool master = false, tAbstractMemoryPool* mempool = NULL, tAbstractMutex* mutex = NULL);
00164 ~tMemoryAllocator();
00165 string getinfo(const tBlock block);
00166 string getinfo(offsettype block);
00167 void dumpmeminfo();
00168 void dumpblocks();
00169 void dumpkeys(const tKeyHint keyhint = tKeyHint());
00170 void reset();
00171 void lock();
00172 void unlock();
00173 tAbstractMutex* getmutex() {return _mutex;};
00174 bool mempool_isvalid() {return (_mempool->getmembase()!=NULL);};
00175 offsettype abs2offset(void* pointer) {return (pointer==NULL)?0:((char*)pointer - _mempool->getmembase());};
00176 void* offset2abs(offsettype offset) {return (offset==0)?NULL:(_mempool->getmembase() + offset);};
00177 tBlockHeader* offset2header(offsettype offset) {return (offset==0)?NULL:((tBlockHeader*)(_mempool->getmembase() + offset));};
00178 tBlock malloc(int size);
00179 tBlock malloc_key(int size, long key);
00180 tBlock malloc_keyhint(int size, long key, tKeyHintStruc &keyhint);
00181 void free(const tBlock &block);
00182 void free_keyhint(const tBlock &block, tKeyHintStruc &keyhint);
00183 friend class tMemoryAllocator_Iterator;
00184 tBlock getfirst(const long key, const tKeyHint keyhint = tKeyHint(), bool match = true);
00185 tBlock getlast(const long key, const tKeyHint keyhint = tKeyHint(), bool match = true);
00186 tMemoryAllocator_Iterator begin(const long key = 0, const tKeyHint keyhint = tKeyHint(), bool match = true);
00187 tMemoryAllocator_Iterator end(const long key = 0, const tKeyHint keyhint = tKeyHint(), bool match = true);
00188 void* getdata(const long key);
00189 };
00190
00193 class tMemoryAllocator_Iterator {
00194 private:
00195 tMemoryAllocator* _malloc;
00196 long _key;
00197 tMemoryAllocator::tBlockHeader* _current;
00198 public:
00199 tMemoryAllocator_Iterator(tMemoryAllocator* malloc, const long key = 0, tMemoryAllocator::tBlockHeader* current = NULL) : _malloc(malloc), _key(key), _current(current) {_malloc->lock();};
00200 ~tMemoryAllocator_Iterator() {_malloc->unlock();};
00201 tMemoryAllocator::tBlock current();
00202 bool next();
00203 bool previous();
00204 };
00205
00208 template <class T>
00209 class tSTLAllocator {
00210 public:
00212 tMemoryAllocator* _malloc;
00213
00214 typedef size_t size_type;
00215 typedef ptrdiff_t difference_type;
00216 typedef T* pointer;
00217 typedef const T* const_pointer;
00218 typedef T& reference;
00219 typedef const T& const_reference;
00220 typedef T value_type;
00222 template <class U>
00223 struct rebind {
00224 typedef tSTLAllocator<U> other;
00225 };
00227 pointer address(reference value) const {
00228 return &value;
00229 }
00231 const_pointer address(const_reference value) const {
00232 return &value;
00233 }
00235 tSTLAllocator() throw() : _malloc(NULL) {};
00237 tSTLAllocator(const tSTLAllocator& allocator) throw() {setmalloc(allocator.getmalloc());};
00238 template<class U> tSTLAllocator(const tSTLAllocator<U>& allocator) throw() {_malloc = allocator._malloc;};
00240 ~tSTLAllocator() throw() {};
00242 size_type max_size () const throw() {
00243 return numeric_limits<size_t>::max() / sizeof(T);
00244 }
00246 pointer allocate(size_type num, const_pointer hint = 0) {
00247 if (hint==NULL) {}
00248 return (pointer)(_malloc->malloc(num*sizeof(T)).data);
00249
00250 }
00252 void construct (pointer p, const T& value) {
00253
00254 new((void*)p)T(value);
00255 }
00257 void destroy(pointer p) {
00258
00259 p->~T();
00260 }
00262 void deallocate (pointer p, size_type num) {
00263 num=0;
00264 _malloc->free(tMemoryAllocator::tBlock((tMemoryAllocator::tBlockHeader*)((char*)p - sizeof(tMemoryAllocator::tBlockHeader))));
00265
00266 }
00268 void setmalloc(tMemoryAllocator* malloc) {_malloc=malloc;};
00270 tMemoryAllocator* getmalloc() const {return _malloc;};
00271 };
00272
00274 template <class T1, class T2>
00275 bool operator== (const tSTLAllocator<T1>& allocator1,
00276 const tSTLAllocator<T2>& allocator2) throw() {
00277 return (allocator1._malloc==allocator2._malloc);
00278 }
00279 template <class T1, class T2>
00280 bool operator!= (const tSTLAllocator<T1>& allocator1,
00281 const tSTLAllocator<T2>& allocator2) throw() {
00282 return (allocator1._malloc!=allocator2._malloc);
00283 }
00284
00286
00287 struct pid_less : public binary_function<pid_t,pid_t,bool>
00288 {
00289 bool operator()(const pid_t& __x, const pid_t& __y) const {
00290 return __x < __y;
00291 }
00292 };
00293
00296 template <class T>
00297 class tSTLShMemAllocator {
00298 public:
00300 typedef map<pid_t, tMemoryAllocator*, pid_less, tSTLShMemAllocator<pid_t> > tProcessMAllocMap;
00301 typedef tProcessMAllocMap* pProcessMAllocMap;
00303 pProcessMAllocMap* _mallocmapptr;
00304 bool _master;
00305
00306 typedef size_t size_type;
00307 typedef ptrdiff_t difference_type;
00308 typedef T* pointer;
00309 typedef const T* const_pointer;
00310 typedef T& reference;
00311 typedef const T& const_reference;
00312 typedef T value_type;
00314 template<class U>
00315 struct rebind {
00316 typedef tSTLShMemAllocator<U> other;
00317 };
00319 pointer address(reference value) const {
00320 return &value;
00321 }
00323 const_pointer address(const_reference value) const {
00324 return &value;
00325 }
00327 tSTLShMemAllocator() throw() : _mallocmapptr(NULL), _master(false) {
00328 };
00330 tSTLShMemAllocator(const tSTLShMemAllocator& allocator) throw() {
00331 _mallocmapptr = allocator._mallocmapptr;
00332 _master = false;
00333 };
00335 template<class U> tSTLShMemAllocator(const tSTLShMemAllocator<U>& allocator) throw() {
00336 _mallocmapptr = allocator._mallocmapptr;
00337 _master = false;
00338 };
00340 ~tSTLShMemAllocator() throw() {
00341 if (_master) {
00342 tProcessMAllocMap* currentmap;
00343 currentmap = *_mallocmapptr;
00344 tProcessMAllocMap tempmap;
00345
00346 tempmap = *currentmap;
00347 *_mallocmapptr = &tempmap;
00348
00349 currentmap->~tProcessMAllocMap();
00350 getmalloc()->free(tMemoryAllocator::tBlock(NULL, currentmap));
00351
00352 getmalloc()->free(tMemoryAllocator::tBlock(NULL, _mallocmapptr));
00353 }
00354 };
00356 size_type max_size () const throw() {
00357 return numeric_limits<size_t>::max() / sizeof(T);
00358 }
00360 pointer allocate(size_type num, const_pointer hint = 0) {
00361 if (hint==NULL) {}
00362 if (_mallocmapptr==NULL) {
00363 return (pointer)(::operator new(num*sizeof(T)));
00364 } else {
00365 if (getmalloc()==NULL) {
00366 debugprint('E', "no memory-allocator for current process found", "tSTLShMemAllocator::allocate");
00367 return NULL;
00368 } else {
00369 return (pointer)(getmalloc()->malloc(num*sizeof(T)).data);
00370 }
00371 }
00372 }
00374 void construct (pointer p, const T& value) {
00375
00376 new((void*)p)T(value);
00377 }
00379 void destroy(pointer p) {
00380
00381 p->~T();
00382 }
00384 void deallocate(pointer p, size_type num) {
00385 num=0;
00386 if (_mallocmapptr==NULL) {
00387 ::operator delete((void*)p);
00388 } else {
00389 if (getmalloc()==NULL) {
00390 debugprint('E', "no memory-allocator for current process found", "tSTLShMemAllocator::deallocate");
00391 } else {
00392 getmalloc()->free(tMemoryAllocator::tBlock(NULL, p));
00393 }
00394 }
00395 }
00397 void setmalloc(tMemoryAllocator* malloc) {
00398
00399 tGuardCurrentScope guard = tGuardCurrentScope(malloc->getmutex());
00400
00401 tProcessMAllocMap* currentmap;
00402 tProcessMAllocMap tempmap;
00403 if (_mallocmapptr!=NULL) {
00404 currentmap = *_mallocmapptr;
00405 tempmap = **_mallocmapptr;
00406 } else {
00407 currentmap = NULL;
00408 }
00409 tempmap[getpid()] = malloc;
00410 debugprint('I', "adding process "+int2str(getpid())+" to process map using memory-allocator "+ptr2str(malloc), "tSTLShMemAllocator::setmalloc");
00411
00412 if (currentmap==NULL) {
00413
00414 tGuardCurrentScope lock = tGuardCurrentScope(malloc->getmutex());
00415
00416 tMemoryAllocator::tBlock memblock = malloc->malloc(sizeof(pProcessMAllocMap));
00417 _mallocmapptr = (pProcessMAllocMap*)(memblock.data);
00418 *_mallocmapptr = &tempmap;
00419
00420 tProcessMAllocMap* newmap;
00421 memblock = malloc->malloc(sizeof(tProcessMAllocMap));
00422 newmap = new((memblock.data))tProcessMAllocMap(pid_less(), *this);
00423
00424 *newmap = **_mallocmapptr;
00425 *_mallocmapptr = newmap;
00426 _master = true;
00427 } else {
00428
00429 *_mallocmapptr = &tempmap;
00430 (*currentmap)[getpid()] = malloc;
00431 *_mallocmapptr = currentmap;
00432 }
00433 };
00435 inline tProcessMAllocMap* getmallocmap() const {return *_mallocmapptr;};
00437 inline tMemoryAllocator* getmalloc() const {return (*_mallocmapptr)->find(getpid())->second;};
00438 };
00439
00441 template <class T1, class T2>
00442 bool operator== (const tSTLShMemAllocator<T1>& allocator1,
00443 const tSTLShMemAllocator<T2>& allocator2) throw() {
00444 return (allocator1._mallocmapptr==allocator2._mallocmapptr);
00445 }
00446 template <class T1, class T2>
00447 bool operator!= (const tSTLShMemAllocator<T1>& allocator1,
00448 const tSTLShMemAllocator<T2>& allocator2) throw() {
00449 return (allocator1._mallocmapptr!=allocator2._mallocmapptr);
00450 }
00451
00452
00453 #endif