Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

ShmAllocator.h

Go to the documentation of this file.
00001 #ifndef __MYALLOC_H
00002 #define __MYALLOC_H
00003 
00004 #include <iostream>
00005 #include <memory>
00006 #include <sys/types.h>
00007 #include <sys/ipc.h>
00008 #include <sys/shm.h>
00009 #include "SemaphoreSet.h"
00010 #include "ExceptionBase.h"
00011 
00012 using namespace std;
00013 using namespace SemSet;
00014 
00015 namespace ShmAllocator 
00016 {
00023     class MemException : public ExceptionBase
00024     {
00025     public:
00029         MemException() : ExceptionBase() {}
00030 
00036         MemException(const char* mess) : ExceptionBase(mess) {}
00037 
00041         ~MemException() {}
00042     };
00043 
00044 
00046     #define ALIGN_SEGMENT(n)    (((n-1)|3)+1)
00047 
00048     #define MAX(a,b)            ((a) >= (b) ? (a) : (b))
00049 
00050     #define ATTR_TO_TYPE(T,A,P) ((T*)((char*)(P)-offsetof(T,A)))
00051 
00058     class BlocksList
00059     {
00063         struct Node
00064         {
00065             Node(const size_t length, Node* next = 0) : length(length), next(next) {}
00066             size_t length;
00067             Node* next;
00068         };
00072         struct ReturnedBlock
00073         {
00074             size_t size;
00075             char block[0];
00076         };
00077 
00078     private:
00079         Node* head;             //the head of the list
00080         size_t totalSize;       //the total size of the block
00081         size_t freeSize;        //the free space left
00082         int numOfBlocks;        //number of nodes in the list
00083         void* blockStart;       //start address of the block
00084         void* blockEnd;         //first address not in the block
00085 
00086     public:
00093         BlocksList(size_t totalSize, void* blockStart) : totalSize(totalSize), blockStart(blockStart)
00094         {
00095             //create a one node list
00096             (char*)blockEnd = (char*)blockStart + totalSize;
00097             freeSize = totalSize;
00098             head = (Node*)blockStart;
00099             new(head) Node(freeSize);
00100             numOfBlocks = 1;
00101         }
00102 
00106         ~BlocksList() {}
00107 
00115         void* getBlock(size_t n)
00116         {
00117             size_t newSize;
00118             Node* tmpNode;
00119             Node* prevNode;
00120             Node* newNext;
00121             ReturnedBlock* returnedBlock;
00122 
00123             //get the real size to allocate
00124             n = MAX(ALIGN_SEGMENT(n + sizeof(ReturnedBlock)), sizeof(Node));
00125             prevNode = NULL;
00126 
00127             //find available space
00128             for (tmpNode = head; tmpNode; tmpNode = tmpNode->next)
00129             {
00130                 if (tmpNode->length >= n)
00131                 {
00132                     //found block
00133                     returnedBlock = (ReturnedBlock*)tmpNode;
00134                     freeSize -= n;
00135                     if ((tmpNode->length > n) && (tmpNode->length - n >= sizeof(Node)))
00136                     {
00137                         newSize = tmpNode->length - n;
00138                         newNext = tmpNode->next;
00139                         if (prevNode == NULL)
00140                         {
00141                             //first link
00142                             (char*)head = (char*)head + n;
00143                             new(head) Node(newSize, newNext);
00144                         }
00145                         else
00146                         {
00147                             //other link
00148                             (char*)tmpNode = (char*)tmpNode + n;
00149                             new(tmpNode) Node(newSize, newNext);
00150                             prevNode->next = tmpNode;
00151                         }
00152                     }
00153                     else 
00154                     {
00155                         //use whole block
00156                         n = tmpNode->length;
00157                         numOfBlocks--;
00158                         if (prevNode == NULL)
00159                             head = head->next;
00160                         else
00161                             prevNode->next = tmpNode->next;
00162                     }
00163                     //write down the size given and return
00164                     returnedBlock->size = n;
00165                     return returnedBlock->block;
00166                 }
00167 
00168                 prevNode = tmpNode;
00169             }
00170 
00171             //found no free space
00172             return NULL;
00173         }
00174 
00180         void returnBlock(void *p) throw(MemException)
00181         {
00182             ReturnedBlock* returnedBlock;
00183             void* curBlockEndAddress;
00184             Node* tmpNode;
00185             Node* prevNode;
00186             Node* returnedNode;
00187 
00188             returnedBlock = ATTR_TO_TYPE(ReturnedBlock, block, p);
00189             (char*)curBlockEndAddress = (char*)returnedBlock + returnedBlock->size;
00190             //sanity check
00191             if (((char*)returnedBlock < (char*)blockStart) || 
00192                 ((char*)curBlockEndAddress > (char*)blockEnd))
00193                 throw MemException("Returning memory not allocated");
00194 
00195             freeSize += returnedBlock->size;
00196             prevNode = NULL;
00197 
00198             //handle adding first node case
00199             if (head == NULL)
00200             {
00201                 head = (Node*)returnedBlock;
00202                 new(head) Node(returnedBlock->size);
00203                 return;
00204             }
00205 
00206             //find the position to keep list sorted
00207             for (tmpNode = head; tmpNode; tmpNode = tmpNode->next)
00208             {
00209                 if ((char*)returnedBlock < (char*)tmpNode)
00210                 {
00211                     returnedNode = (Node*)returnedBlock;
00212                     numOfBlocks++;
00213                     if (prevNode == NULL)
00214                     {
00215                         //adding before the head
00216                         new(returnedNode) Node(returnedBlock->size, head);
00217                         head = returnedNode;
00218                     }
00219                     else
00220                     {
00221                         //regular add
00222                         prevNode->next = returnedNode;
00223                         new(returnedNode) Node(returnedBlock->size, tmpNode);
00224                     }
00225                     //connect to previous node if necessary
00226                     if ((prevNode) && ((char*)prevNode + prevNode->length == (char*)returnedNode))
00227                     {
00228                         prevNode->length += returnedNode->length;
00229                         prevNode->next = returnedNode->next;
00230                         returnedNode = prevNode;        //to check if we need to connect to next node
00231                         numOfBlocks--;
00232                     }
00233                     //connect to next node if necessary
00234                     if ((returnedNode->next) && ((char*)returnedNode + returnedNode->length == (char*)returnedNode->next))
00235                     {
00236                         returnedNode->length += returnedNode->next->length;
00237                         returnedNode->next = returnedNode->next->next;
00238                         numOfBlocks--;
00239                     }
00240                     return;
00241                 }
00242 
00243                 prevNode = tmpNode;
00244             }
00245 
00246             //add new last node case
00247             returnedNode = (Node*)returnedBlock;
00248             numOfBlocks++;
00249             prevNode->next = returnedNode;
00250             new(returnedNode) Node(returnedBlock->size);
00251             //connect to previous node if necessary
00252             if ((char*)prevNode + prevNode->length == (char*)returnedNode)
00253             {
00254                 prevNode->length += returnedNode->length;
00255                 prevNode->next = returnedNode->next;
00256                 numOfBlocks--;
00257             }
00258             return;
00259         }
00260 
00266         size_t accumFreeMemorySize()
00267         {
00268             Node* tmpNode;
00269             size_t totalFree = 0;
00270 
00271             for (tmpNode = head; tmpNode; tmpNode = tmpNode->next)
00272                 totalFree += tmpNode->length;
00273 
00274             return totalFree;
00275         }
00276 
00282         size_t getTotalSize()
00283         {
00284             return totalSize;
00285         }
00286 
00292         size_t getFreeSize()
00293         {
00294             return freeSize;
00295         }
00296 
00302         size_t getNumOfBlocks()
00303         {
00304             return numOfBlocks;
00305         }
00306     };
00307 
00308 
00316     class MemAlloc
00317     {
00318     private:
00319         static void *chunk;         //pointer to the shared memory block
00320         static int shmId;           //shared memory identifier
00321         static SemaphoreSet* sem;   //block associated semaphore
00322         static bool freeMemoryFlag; //indicates whether we want to really free the memory (time consuming)
00323     
00324     public:
00325         static BlocksList* bl;      //free blocks list
00326 
00332         static void initialize(unsigned sizeBits, bool freeMemory = false) throw(MemException);
00333 
00337         static void MemAlloc::destroy();
00338 
00346         static void* allocate(size_t size) throw(MemException);
00347     
00353         static void deallocate(void* p);
00354     };
00355 
00356 
00363     class ObjectFactory
00364     {
00365     private:
00366 
00367     public:
00375         template <typename T>
00376         static T* getNewObject()
00377         {
00378             T* ret = (T*)MemAlloc::allocate(sizeof(T));
00379             new(ret) T();
00380 
00381             return ret;
00382         }
00383 
00390         template <typename T>
00391         static void returnObject(T* obj)
00392         {
00393             obj->~T();
00394             MemAlloc::deallocate(obj);
00395         }
00396     };
00397 
00404     template <typename T>
00405     class Allocator
00406     {
00407     private:
00408     
00409     public:
00410         typedef size_t size_type;               
00411         typedef ptrdiff_t difference_type;      
00412         typedef T* pointer;                     
00413         typedef const T* const_pointer;         
00414         typedef T& reference;                   
00415         typedef const T& const_reference;       
00416         typedef T value_type;                   
00421         template <typename T1>
00422             struct rebind
00423             { 
00424                 typedef Allocator<T1> other; 
00425             };
00426     
00430         Allocator() {}
00431 
00437         Allocator(const Allocator&) {}
00438 
00444         template <typename T1>
00445             Allocator(const Allocator<T1>&) {}
00446 
00450         ~Allocator() {}
00451     
00459         pointer address(reference x) const { return &x; }
00460     
00468         const_pointer address(const_reference x) const { return &x; }
00469 
00470 
00478         pointer allocate(size_type n, const void* = 0)
00479         {
00480             T* ret = NULL;
00481             if (n) 
00482                 ret = (pointer)MemAlloc::allocate(n * sizeof(value_type));
00483             return ret;
00484         }
00485     
00492         void deallocate(pointer p, size_type n)
00493         {
00494             if (n != 0)
00495                 MemAlloc::deallocate(p);
00496         }
00497     
00503         size_type max_size() const { return size_t(-1) / sizeof(T); }
00504     
00511         void construct(pointer p, const T& val) { new(p) T(val); }
00512 
00518         void destroy(pointer p) { p->~T(); }
00519     };
00520 
00521 }
00522 
00523 #endif //__MYALLOC_H

Generated on Thu Jan 27 10:06:44 2005 for ShmAllocator by doxygen 1.3.6