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