SingleList.hpp
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 #ifndef ORO_SINGLE_LIST_HPP
00040 #define ORO_SINGLE_LIST_HPP
00041
00042 #include "os/CAS.hpp"
00043 #include <boost/shared_ptr.hpp>
00044 #include "MemoryPool.hpp"
00045
00046 namespace RTT
00047 {
00064 template<class DataType_>
00065 class SingleList
00066 {
00067 public:
00068 typedef DataType_ DataType;
00069 protected:
00070 struct NodeType
00071 {
00072 typedef NodeType* NodeType_sptr;
00073 DataType key;
00074 NodeType_sptr next;
00075
00076 NodeType(const DataType& data)
00077 : key(data)
00078 {}
00079
00080 NodeType()
00081 : key()
00082 {}
00083 };
00084
00088 typedef NodeType Node;
00092 typedef typename NodeType::NodeType_sptr Node_sptr;
00093
00094 MemoryPool<Node> mpool;
00095
00096 Node_sptr head;
00097 Node_sptr tail;
00098
00099 Node_sptr searchKey(const DataType& search_key, Node_sptr& left_node)
00100 {
00101 Node_sptr left_node_next, right_node;
00102 search_again:
00103 do {
00104 Node_sptr t = this->head;
00105 Node_sptr t_next = this->head->next;
00106
00107 do {
00108 if (!is_marked_reference(t_next)) {
00109 left_node = t;
00110 left_node_next = t_next;
00111 }
00112 t = get_unmarked_reference(t_next);
00113 if (t == this->tail)
00114 break;
00115 t_next = t->next;
00116
00117 } while ( is_marked_reference(t_next) ||
00118 !(t->key == search_key ||
00119 t == this->tail));
00120 right_node = t;
00121
00122 if (left_node_next == right_node)
00123 if ((right_node != this->tail) && is_marked_reference(right_node->next))
00124 goto search_again;
00125 else
00126 return right_node;
00127
00128 if (OS::CAS(&(left_node->next), left_node_next, right_node)) {
00129 mpool.deallocate( get_unmarked_reference(left_node_next) );
00130 if ((right_node != this->tail) && is_marked_reference(right_node->next))
00131 goto search_again;
00132 else
00133 return right_node;
00134 }
00135 } while (true);
00136 }
00137
00138
00139 template< class F>
00140 Node_sptr searchEnd(const F& foo, Node_sptr& left_node)
00141 {
00142 Node_sptr left_node_next;
00143
00144 Node_sptr t = this->head->next;
00145 Node_sptr t_next = t->next;
00146
00147 if ( t == tail ) {
00148 left_node = head;
00149 return tail;
00150 }
00151
00152 do {
00153 DataType data( t->key );
00154 if (!is_marked_reference(t_next)) {
00155 left_node = t;
00156 left_node_next = t_next;
00157
00158 foo( data );
00159 }
00160 t = get_unmarked_reference(t_next);
00161 if (t == this->tail)
00162 break;
00163 t_next = t->next;
00164
00165 } while ( is_marked_reference(t_next) ||
00166 t != this->tail );
00167
00168
00169 return t;
00170 }
00171
00172 bool is_marked_reference(Node* n)
00173 {
00174 unsigned int v = reinterpret_cast<unsigned int>(n);
00175 return (v%2) == 1;
00176 }
00177
00178 Node* get_unmarked_reference(Node* n)
00179 {
00180 unsigned int v = reinterpret_cast<unsigned int>(n);
00181 return reinterpret_cast<Node*>( v & -2 );
00182 }
00183
00184 Node* get_marked_reference(Node* n)
00185 {
00186 unsigned int v = reinterpret_cast<unsigned int>(n);
00187 return reinterpret_cast<Node*>( v | 1);
00188 }
00189 public:
00190
00194 SingleList()
00195 {
00196 mpool.reserve();
00197 mpool.reserve();
00198 head = mpool.allocate();
00199 tail = mpool.allocate();
00200
00201 head->next = tail;
00202 }
00203
00204 ~SingleList()
00205 {
00206 mpool.deallocate(head);
00207 mpool.deallocate(tail);
00208 }
00209
00213 void reserve(size_t n = 1)
00214 { size_t i(0); while (i++ < n) mpool.reserve(); }
00215
00219 void shrink(size_t n = 1)
00220 { size_t i(0); while (i++ < n) mpool.shrink(); }
00221
00225 bool empty() const
00226 {
00227 return head->next == tail;
00228 }
00229
00235 bool insert(const DataType& key)
00236 {
00237 Node_sptr new_node( mpool.allocate() );
00238 Node_sptr right_node, left_node;
00239
00240 new_node->key = key;
00241 do {
00242 right_node = this->searchKey(key, left_node);
00243 if ((right_node != tail) && (right_node->key == key )) {
00244 mpool.deallocate( new_node );
00245 return false;
00246 }
00247 new_node->next = right_node;
00248 if (OS::CAS(&(left_node->next), right_node, new_node))
00249 return true;
00250 } while (true);
00251 }
00252
00258 bool erase(const DataType& search_key)
00259 {
00260 Node_sptr right_node, right_node_next, left_node;
00261
00262 do {
00263 right_node = searchKey(search_key, left_node);
00264 if (( right_node == tail) || !(right_node->key == search_key) )
00265 return false;
00266 right_node_next = right_node->next;
00267 if (!is_marked_reference(right_node_next))
00268 if (OS::CAS( &(right_node->next), right_node_next, get_marked_reference(right_node_next)))
00269 break;
00270 } while(true);
00271 if (!OS::CAS(&(left_node->next), right_node, right_node_next))
00272 right_node = search(right_node->key, left_node);
00273 else
00274 mpool.deallocate( get_unmarked_reference(right_node) );
00275 return true;
00276 }
00277
00283 bool hasKey(const DataType& search_key)
00284 {
00285 Node_sptr right_node, left_node;
00286
00287 right_node = searchKey( search_key, left_node);
00288 if ((right_node == tail) || !(right_node->key == search_key))
00289 return false;
00290 else
00291 return true;
00292 }
00293
00308 template<class Function>
00309 void applyOnData(const Function& f )
00310 {
00311
00312 Node_sptr t = this->head;
00313 Node_sptr t_next = this->head->next;
00314
00315
00316
00317 do {
00318
00319 t = get_unmarked_reference(t_next);
00320 if (t == this->tail)
00321 return;
00322 if (!is_marked_reference(t_next)) {
00323
00324
00325 f( t->key );
00326 }
00327 t_next = t->next;
00328 } while ( true );
00329
00330 }
00331
00339 template<class Function>
00340 void applyOnCopy(const Function& f )
00341 {
00342
00343 Node_sptr t;
00344 Node_sptr t_next = this->head->next;
00345
00346
00347
00348 do {
00349
00350 t = get_unmarked_reference(t_next);
00351 if (t == this->tail)
00352 return;
00353
00354 DataType d(t->key);
00355 if (!is_marked_reference(t_next)) {
00356
00357
00358 f( d );
00359 }
00360 t_next = t->next;
00361 } while ( true );
00362
00363 }
00364 };
00365
00366 }
00367
00368 #endif