SortedList.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_SORTED_LIST_HPP
00040 #define ORO_SORTED_LIST_HPP
00041
00042 #include "os/CAS.hpp"
00043 #include <boost/shared_ptr.hpp>
00044 #include "MemoryPool.hpp"
00045
00046 namespace RTT
00047 {
00062 template<class DataType_>
00063 class SortedList
00064 {
00065 public:
00066 typedef DataType_ DataType;
00067 protected:
00068 struct NodeType
00069 {
00070 typedef NodeType* NodeType_sptr;
00071 DataType key;
00072 NodeType_sptr next;
00073
00074 NodeType(const DataType& data)
00075 : key(data)
00076 {}
00077
00078 NodeType()
00079 : key()
00080 {}
00081 };
00082
00086 typedef NodeType Node;
00090 typedef typename NodeType::NodeType_sptr Node_sptr;
00091
00092 MemoryPool<Node> mpool;
00093
00094 Node_sptr head;
00095 Node_sptr tail;
00096
00097 Node_sptr search(const DataType& search_key, Node_sptr& left_node)
00098 {
00099 Node_sptr left_node_next, right_node;
00100 search_again:
00101 do {
00102 Node_sptr t = this->head;
00103 Node_sptr t_next = this->head->next;
00104
00105 do {
00106 if (!is_marked_reference(t_next)) {
00107 left_node = t;
00108 left_node_next = t_next;
00109 }
00110 t = get_unmarked_reference(t_next);
00111 if (t == this->tail)
00112 break;
00113 t_next = t->next;
00114 } while (is_marked_reference(t_next) || (t->key < search_key));
00115 right_node = t;
00116
00117 if (left_node_next == right_node)
00118 if ((right_node != this->tail) && is_marked_reference(right_node->next))
00119 goto search_again;
00120 else
00121 return right_node;
00122
00123 if (OS::CAS(&(left_node->next), left_node_next, right_node)) {
00124 mpool.deallocate( get_unmarked_reference(left_node_next) );
00125 if ((right_node != this->tail) && is_marked_reference(right_node->next))
00126 goto search_again;
00127 else
00128 return right_node;
00129 }
00130 } while (true);
00131 }
00132
00133 bool is_marked_reference(Node* n)
00134 {
00135 unsigned int v = reinterpret_cast<unsigned int>(n);
00136 return (v%2) == 1;
00137 }
00138
00139 Node* get_unmarked_reference(Node* n)
00140 {
00141 unsigned int v = reinterpret_cast<unsigned int>(n);
00142 return reinterpret_cast<Node*>( v & -2 );
00143 }
00144
00145 Node* get_marked_reference(Node* n)
00146 {
00147 unsigned int v = reinterpret_cast<unsigned int>(n);
00148 return reinterpret_cast<Node*>( v | 1);
00149 }
00150 public:
00151
00155 SortedList()
00156 {
00157 mpool.reserve();
00158 mpool.reserve();
00159 head = mpool.allocate();
00160 tail = mpool.allocate();
00161
00162 head->next = tail;
00163 }
00164
00165 ~SortedList()
00166 {
00167 mpool.deallocate(head);
00168 mpool.deallocate(tail);
00169 }
00170
00174 void reserve(size_t n = 1)
00175 { size_t i(0); while (i++ < n) mpool.reserve(); }
00176
00180 void shrink(size_t n = 1)
00181 { size_t i(0); while (i++ < n) mpool.shrink(); }
00182
00186 bool empty() const
00187 {
00188 return head->next == tail;
00189 }
00190
00196 bool insert(const DataType& key)
00197 {
00198 Node_sptr new_node( mpool.allocate() );
00199 Node_sptr right_node, left_node;
00200
00201 new_node->key = key;
00202 do {
00203 right_node = this->search(key, left_node);
00204 if ((right_node != tail) && (right_node->key == key )) {
00205 mpool.deallocate( new_node );
00206 return false;
00207 }
00208 new_node->next = right_node;
00209 if (OS::CAS(&(left_node->next), right_node, new_node))
00210 return true;
00211 } while (true);
00212 }
00213
00219 bool erase(const DataType& search_key)
00220 {
00221 Node_sptr right_node, right_node_next, left_node;
00222
00223 do {
00224 right_node = search(search_key, left_node);
00225 if (( right_node == tail) || !(right_node->key == search_key) )
00226 return false;
00227 right_node_next = right_node->next;
00228 if (!is_marked_reference(right_node_next))
00229 if (OS::CAS( &(right_node->next), right_node_next, get_marked_reference(right_node_next)))
00230 break;
00231 } while(true);
00232 if (!OS::CAS(&(left_node->next), right_node, right_node_next))
00233 right_node = search(right_node->key, left_node);
00234 else
00235 mpool.deallocate( get_unmarked_reference(right_node) );
00236 return true;
00237 }
00238
00244 bool hasKey(const DataType& search_key)
00245 {
00246 Node_sptr right_node, left_node;
00247
00248 right_node = search( search_key, left_node);
00249 if ((right_node == tail) || !(right_node->key == search_key))
00250 return false;
00251 else
00252 return true;
00253 }
00254
00269 template<class Function>
00270 void applyOnData(const Function& f )
00271 {
00272
00273 Node_sptr t = this->head;
00274 Node_sptr t_next = this->head->next;
00275
00276
00277
00278 do {
00279
00280 t = get_unmarked_reference(t_next);
00281 if (t == this->tail)
00282 return;
00283 if (!is_marked_reference(t_next)) {
00284
00285
00286 f( t->key );
00287 }
00288 t_next = t->next;
00289 } while ( true );
00290
00291 }
00292
00300 template<class Function>
00301 void applyOnCopy(const Function& f )
00302 {
00303
00304 Node_sptr t;
00305 Node_sptr t_next = this->head->next;
00306
00307
00308
00309 do {
00310
00311 t = get_unmarked_reference(t_next);
00312 if (t == this->tail)
00313 return;
00314
00315 DataType d(t->key);
00316 if (!is_marked_reference(t_next)) {
00317
00318
00319 f( d );
00320 }
00321 t_next = t->next;
00322 } while ( true );
00323
00324 }
00325 };
00326
00327 }
00328
00329 #endif