00001
00002
00003 #ifndef COMMONS_REGION_H
00004 #define COMMONS_REGION_H
00005
00006 #include <limits>
00007
00008
00009 #include <set>
00010 #include <vector>
00011 #include <pthread.h>
00012
00013 namespace commons
00014 {
00015
00016 using namespace std;
00017
00021 const size_t default_chunk_size = 10000000;
00022
00026 struct chunk
00027 {
00028 size_t size;
00029 char* data;
00030 };
00031
00036 class mem_region
00037 {
00038 private:
00039 vector<chunk> chunks;
00044 const size_t chunk_size;
00045 size_t top;
00046 int refcount;
00047 set<pthread_t> threads;
00048
00049 public:
00050 mem_region() :
00051 chunk_size(default_chunk_size),
00052 top(0),
00053 refcount(0)
00054 {
00055
00056 chunks.push_back((chunk) {chunk_size, new char[chunk_size]});
00057 }
00058
00059 ~mem_region()
00060 {
00061
00062 for (unsigned int i = 0; i < chunks.size(); i++) {
00063 delete [] chunks[i].data;
00064 }
00065 }
00066
00067 void addref() { ++refcount; }
00068 void decref() { if (--refcount == 0) { delete this; } }
00069
00070 void *alloc_mem(size_t n)
00071 {
00072
00073
00074
00075
00076 chunk* last = &chunks.back();
00077 if (top + n > last->size) {
00078 size_t sz = max(n, chunk_size);
00079 chunk c = {sz, new char[sz]};
00080 if (n > chunk_size) {
00081
00082 chunks.insert(chunks.begin(), c);
00083 return c.data;
00084 } else {
00085
00086 chunks.push_back(c);
00087 top = 0;
00088 last = &chunks.back();
00089 }
00090 }
00091
00092 size_t old_top = top;
00093 top += n;
00094 return last->data + old_top;
00095 }
00096 };
00097
00102 template <class T>
00103 class region_alloc {
00104 public:
00105
00106 typedef T value_type;
00107 typedef T* pointer;
00108 typedef const T* const_pointer;
00109 typedef T& reference;
00110 typedef const T& const_reference;
00111 typedef std::size_t size_type;
00112 typedef std::ptrdiff_t difference_type;
00113
00114 typedef mem_region pool_type;
00115
00119 template <class U>
00120 struct rebind {
00121 typedef region_alloc<U> other;
00122 };
00123
00127 pointer address (reference value) const { return &value; }
00128 const_pointer address (const_reference value) const { return &value; }
00129
00133 region_alloc() throw() {
00134 region = new pool_type;
00135 region->addref();
00136 }
00137
00143 region_alloc(const region_alloc& src) throw() {
00144 region = src.region;
00145 region->addref();
00146 }
00147
00151 template <class U>
00152 region_alloc (const region_alloc<U> &src) throw() {
00153 region = src.region;
00154 region->addref();
00155 }
00156
00160 ~region_alloc() throw() { region->decref(); }
00161
00166 size_type max_size() const throw()
00167 {
00168 return numeric_limits<size_t>::max() / sizeof(T);
00169 }
00170
00174 pointer allocate(size_type num, const void* = 0)
00175 {
00176 return reinterpret_cast<pointer>(region->alloc_mem(num * sizeof(T)));
00177 }
00178
00183 void construct(pointer p, const T& value) {
00184 new (static_cast<void*>(p)) T(value);
00185 }
00186
00190 void destroy(pointer p) { p->~T(); }
00191
00195 void deallocate(pointer p, size_type num) {}
00196
00197
00198 pool_type *region;
00199 };
00200
00205 template <class T1, class T2>
00206 bool operator== (const region_alloc<T1>&, const region_alloc<T2>&) throw() {
00207 return true;
00208 }
00209
00214 template <class T1, class T2>
00215 bool operator!= (const region_alloc<T1>&, const region_alloc<T2>&) throw() {
00216 return false;
00217 }
00218
00219 }
00220
00221 #endif