Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

frame_memory.h

00001 /***************************************************************************
00002                            frame_memory.h  -  description
00003                              -------------------
00004     begin                : Mit Jun 25 2003
00005     copyright            : (C) 2003 by Dirk Henrici
00006     email                : henrici@informatik.uni-kl.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of license found in "COPYING".                     *
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 //Forward-Deklarationen
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   // Typendefinitionen
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     //original:  return (pointer)(::operator new(num*sizeof(T)));
00250   }
00252   void construct (pointer p, const T& value) {
00253     //initialize memory with placement new
00254     new((void*)p)T(value);
00255   }
00257   void destroy(pointer p) {
00258     //destroy objects by calling their destructor
00259     p->~T();
00260   }
00262   void deallocate (pointer p, size_type num) {
00263     num=0; // damit keine Compilerwarnung
00264     _malloc->free(tMemoryAllocator::tBlock((tMemoryAllocator::tBlockHeader*)((char*)p - sizeof(tMemoryAllocator::tBlockHeader))));
00265     //original:  ::operator delete((void*)p);
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 // Darf nicht in Deklaration für Template stehen, weil für alle Allokatoren gleich
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/*less<pid_t>*/, tSTLShMemAllocator<pid_t> > tProcessMAllocMap;
00301   typedef tProcessMAllocMap* pProcessMAllocMap; 
00303   pProcessMAllocMap* _mallocmapptr;
00304   bool _master;
00305   // Typendefinitionen
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       //temporäres Mapping im normalen Speicher anlegen     
00346       tempmap = *currentmap;
00347       *_mallocmapptr = &tempmap;
00348       //Map im Shared-Memory freigeben 
00349       currentmap->~tProcessMAllocMap();
00350       getmalloc()->free(tMemoryAllocator::tBlock(NULL, currentmap));
00351       //Block mit Zeiger im SharedMemory freigeben
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     //Initialisiere mit "placement new"
00376     new((void*)p)T(value);
00377   }
00379   void destroy(pointer p) {
00380     //Aufrufen des Destruktors
00381     p->~T();
00382   }
00384   void deallocate(pointer p, size_type num) {
00385     num=0; //damit keine Compilerwarnung
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     //Shared-Memory vor Zugriff durch andere schützen
00399     tGuardCurrentScope guard = tGuardCurrentScope(malloc->getmutex());
00400     //temporäres Mapping im "normalen" Speicherbereich anlegen
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     //neues Paar PID-MAlloc einfügen     
00412     if (currentmap==NULL) {
00413       //Shared-Memory für aktuellen Scope sperren, damit nicht andere Prozesse zur gleichen Zeit darauf zugreifen
00414       tGuardCurrentScope lock = tGuardCurrentScope(malloc->getmutex());
00415       //Speicherbereich für Zeiger auf Prozeß-MAlloc-Mapping einrichten
00416       tMemoryAllocator::tBlock memblock = malloc->malloc(sizeof(pProcessMAllocMap));
00417       _mallocmapptr = (pProcessMAllocMap*)(memblock.data);
00418       *_mallocmapptr = &tempmap;
00419       //Map im Shared-Memory/Memory-Allocator-Bereich anlegen      
00420       tProcessMAllocMap* newmap;
00421       memblock = malloc->malloc(sizeof(tProcessMAllocMap));
00422       newmap = new((memblock.data))tProcessMAllocMap(pid_less(), *this);
00423       //Daten kopieren und neues Mapping verwenden
00424       *newmap = **_mallocmapptr;
00425       *_mallocmapptr = newmap;
00426       _master = true;
00427     } else {
00428       //neue Zuordnung einfügen
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

Generated on Wed Sep 3 08:36:33 2003 for STL shared memory allocator by doxygen1.2.18