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;
00080 size_t totalSize;
00081 size_t freeSize;
00082 int numOfBlocks;
00083 void* blockStart;
00084 void* blockEnd;
00085
00086 public:
00093 BlocksList(size_t totalSize, void* blockStart) : totalSize(totalSize), blockStart(blockStart)
00094 {
00095
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
00124 n = MAX(ALIGN_SEGMENT(n + sizeof(ReturnedBlock)), sizeof(Node));
00125 prevNode = NULL;
00126
00127
00128 for (tmpNode = head; tmpNode; tmpNode = tmpNode->next)
00129 {
00130 if (tmpNode->length >= n)
00131 {
00132
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
00142 (char*)head = (char*)head + n;
00143 new(head) Node(newSize, newNext);
00144 }
00145 else
00146 {
00147
00148 (char*)tmpNode = (char*)tmpNode + n;
00149 new(tmpNode) Node(newSize, newNext);
00150 prevNode->next = tmpNode;
00151 }
00152 }
00153 else
00154 {
00155
00156 n = tmpNode->length;
00157 numOfBlocks--;
00158 if (prevNode == NULL)
00159 head = head->next;
00160 else
00161 prevNode->next = tmpNode->next;
00162 }
00163
00164 returnedBlock->size = n;
00165 return returnedBlock->block;
00166 }
00167
00168 prevNode = tmpNode;
00169 }
00170
00171
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
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
00199 if (head == NULL)
00200 {
00201 head = (Node*)returnedBlock;
00202 new(head) Node(returnedBlock->size);
00203 return;
00204 }
00205
00206
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
00216 new(returnedNode) Node(returnedBlock->size, head);
00217 head = returnedNode;
00218 }
00219 else
00220 {
00221
00222 prevNode->next = returnedNode;
00223 new(returnedNode) Node(returnedBlock->size, tmpNode);
00224 }
00225
00226 if ((prevNode) && ((char*)prevNode + prevNode->length == (char*)returnedNode))
00227 {
00228 prevNode->length += returnedNode->length;
00229 prevNode->next = returnedNode->next;
00230 returnedNode = prevNode;
00231 numOfBlocks--;
00232 }
00233
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
00247 returnedNode = (Node*)returnedBlock;
00248 numOfBlocks++;
00249 prevNode->next = returnedNode;
00250 new(returnedNode) Node(returnedBlock->size);
00251
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;
00320 static int shmId;
00321 static SemaphoreSet* sem;
00322 static bool freeMemoryFlag;
00323
00324 public:
00325 static BlocksList* bl;
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