00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #ifndef RTT_TSPOOL_HPP_
00047 #define RTT_TSPOOL_HPP_
00048
00049 #include "../os/CAS.hpp"
00050 #include <assert.h>
00051
00052 namespace RTT
00053 {
00054 namespace internal
00055 {
00056
00061 template<typename T>
00062 class TsPool
00063 {
00064 public:
00065 typedef T value_t;
00066 private:
00067 union Pointer_t
00068 {
00069 unsigned int value;
00070 struct _ptr_type
00071 {
00072 unsigned short tag;
00073 unsigned short index;
00074 } ptr;
00075 };
00076
00082 struct Item
00083 {
00084 value_t value;
00085 volatile Pointer_t next;
00086
00087 Item() :
00088 value(value_t())
00089 {
00090 next.value = 0;
00091 }
00092 };
00093
00094 Item* pool;
00095 Item head;
00096
00097 unsigned int pool_size, pool_capacity;
00098 public:
00099
00100 typedef unsigned int size_type;
00105 TsPool(unsigned int ssize, const T& sample = T()) :
00106 pool_size(0), pool_capacity(ssize)
00107 {
00108 pool = new Item[ssize];
00109 data_sample( sample );
00110 }
00111
00112 ~TsPool()
00113 {
00114 #ifndef NDEBUG
00115
00116 unsigned int i = 0, endseen = 0;
00117 for (; i < pool_capacity; i++)
00118 {
00119 if (pool[i].next.ptr.index == (unsigned short) -1)
00120 {
00121 ++endseen;
00122 }
00123 }
00124 assert( endseen == 1);
00125 assert( size() == pool_capacity && "TsPool: not all pieces were deallocated !" );
00126 #endif
00127 delete[] pool;
00128 }
00129
00137 void clear()
00138 {
00139 for (unsigned int i = 0; i < pool_capacity; i++)
00140 {
00141 pool[i].next.ptr.index = i + 1;
00142 }
00143 pool[pool_capacity - 1].next.ptr.index = (unsigned short) -1;
00144 head.next.ptr.index = 0;
00145 }
00146
00153 void data_sample(const T& sample) {
00154 for (unsigned int i = 0; i < pool_capacity; i++)
00155 pool[i].value = sample;
00156 clear();
00157 }
00158
00159 value_t* allocate()
00160 {
00161 volatile Pointer_t oldval;
00162 volatile Pointer_t newval;
00163 Item* item;
00164 do
00165 {
00166 oldval.value = head.next.value;
00167
00168 if (oldval.ptr.index == (unsigned short) -1)
00169 {
00170 return 0;
00171 }
00172 item = &pool[oldval.ptr.index];
00173 newval.ptr.index = item->next.ptr.index;
00174 newval.ptr.tag = oldval.ptr.tag + 1;
00175 } while (!os::CAS(&head.next.value, oldval.value, newval.value));
00176 return &item->value;
00177 }
00178
00179 bool deallocate(T* Value)
00180 {
00181 if (Value == 0)
00182 {
00183 return false;
00184 }
00185 assert(Value >= (T*) &pool[0] && Value <= (T*) &pool[pool_capacity]);
00186 volatile Pointer_t oldval;
00187 Pointer_t head_next;
00188 Item* item = reinterpret_cast<Item*> (Value);
00189 do
00190 {
00191 oldval.value = head.next.value;
00192 item->next.value = oldval.value;
00193 head_next.ptr.index = (item - pool);
00194 head_next.ptr.tag = oldval.ptr.tag + 1;
00195 } while (!os::CAS(&head.next.value, oldval.value, head_next.value));
00196 return true;
00197 }
00198
00205 unsigned int size()
00206 {
00207 unsigned int ret = 0;
00208 volatile Item* oldval;
00209 oldval = &head;
00210 while ( oldval->next.ptr.index != (unsigned short) -1) {
00211 ++ret;
00212 oldval = &pool[oldval->next.ptr.index];
00213 assert(ret <= pool_capacity);
00214 }
00215 return ret;
00216 }
00217
00222 unsigned int capacity()
00223 {
00224 return pool_capacity;
00225 }
00226
00227 private:
00228
00229 };
00230 }
00231 }
00232
00233 #endif