Tervel  1.0.0
A collection of wait-free containers and algorithms.
pop_helper.h
Go to the documentation of this file.
1 
2 
3 class PopHelper: public Helper{
4 public:
5  std::atomic<void *> child;
7  void init(PopOp *cop){
8  assert(sizeof(PopHelper) <= ALIGNLEN);
9  child=NULL;
10  type=dt_popBack;
11  controlOp=cop;
12  }
14  init(NULL);
15  };
17  init(cop);
18  };
19 
20  bool complete(WFVector *vec, int pos);
21 
22  bool getResult(void *&v);
23  bool tryFree();
24 
25 
26  bool watch(void *p, ArrayElement *a){
27 
28  rc_count.fetch_add(1);
29 
30  if (a->load() != p){
31  rc_count.fetch_add(-1);
32  return false;
33  }
34 
35 
36  if (controlOp){
37  controlOp->rc_count.fetch_add(1);
38  if (a->load() != p){
39  rc_count.fetch_add(-1);
40  controlOp->rc_count.fetch_add(-1);
41  return false;
42  }
43  }
44 
45  return true;
46  };
47 
48  void unwatch(){
49  rc_count.fetch_add(-1);
50 
51  if (controlOp){
52  controlOp->rc_count.fetch_add(-1);
53  }
54  };
55  bool isWatched(){
56  return (rc_count.load() !=0);
57  };
58 
59  void * readThrough(){
60  return NOT_VALUE;
61  };
62 
63 };
64 
65 
66 class PopSubHelper: public Helper{
67 public:
68  void *value;
70 
71  void init(PopHelper *p){
72  assert(sizeof(PopSubHelper) <= ALIGNLEN);
73 
74  parent=p;
75  type=dt_popBackH;
76  value=NOT_VALUE;
77  };
78 
80  init(p);
81  };
82 
83  void * getValue();
84  bool complete(WFVector *vec, int pos);
85  bool tryFree();
86 
87  bool watch(void *p, ArrayElement *a){
88 
89  rc_count.fetch_add(1);
90 
91  if (a->load() != p){
92  rc_count.fetch_add(-1);
93  return false;
94  }
95 
96  parent->rc_count.fetch_add(1);
97  if (a->load() != p){
98  rc_count.fetch_add(-1);
99  parent->rc_count.fetch_add(-1);
100  return false;
101  }
102 
103  if (parent->controlOp){
104  parent->controlOp->rc_count.fetch_add(1);
105  if (a->load() != p){
106  parent->controlOp->rc_count.fetch_add(-1);
107  rc_count.fetch_add(-1);
108  parent->rc_count.fetch_add(-1);
109  return false;
110  }
111  }
112 
113  return true;
114  };
115 
116  void unwatch(){
117  rc_count.fetch_add(-1);
118  parent->rc_count.fetch_add(-1);
119  if (parent->controlOp){
120  parent->controlOp->rc_count.fetch_add(-1);
121  }
122  };
123  bool isWatched(){
124  return (rc_count.load() !=0);
125  };
126 
127  void * readThrough(){
128  return getValue();
129  };
130 
131 };
132 
134 
135  void *expected=parent->child.load();
136  if (expected== NULL){
137  if (parent->child.compare_exchange_strong(expected, (void *)this)){
138  expected=this;
139  }
140  }
141 
142 
143  if (expected == this){
144  if(parent->controlOp != NULL ){
145  if(parent->controlOp->assoc.load()==parent){
146  return NOT_VALUE;
147  }
148  }
149  else{
150  return NOT_VALUE;
151  }
152 
153 
154  }
155  return value;
156 
157 }
158 
159 
160 
161 bool PopSubHelper::complete(WFVector *vec, int pos){
162  assert(type == dt_popBackH );
163  void *newValue;
164  void *e=NULL;
165 
166  PopHelper *t=NULL;
167  if( (parent->child.compare_exchange_strong(e, (void *)this) || e==this) ){
168  if(parent->controlOp == NULL){
169  newValue=NOT_VALUE;
170  }
171  else if (parent->controlOp->assoc.compare_exchange_strong(t, parent) || (t==parent) ){
172  newValue=NOT_VALUE;
173  }
174  else{
175  newValue=value;
176  }
177 
178  }
179  else {
180  newValue=value;
181  }
182 
183  ArrayElement *spot=vec->getSpot(pos);
184 
185  void *temp=Helper::mark(this);
186  spot->compare_exchange_strong(temp, newValue);
187  return true;
188 
189 };
190 
191 bool PopHelper::getResult(void *&v){
192  if (child.load()!= (void *)0x1 ) {
193 
194  if(controlOp){
195  PopHelper *t=NULL;
196  if(controlOp->assoc.compare_exchange_strong(t, this) || t==this){
197  PopSubHelper *temp=(PopSubHelper *)(child.load());
198  v=temp->value;
199  return true;
200  }
201  }
202  else{
203  PopSubHelper *temp=(PopSubHelper *)(child.load());
204  v=temp->value;
205  return true;
206  }
207 
208  }
209  return false;
210 }
211 
212 
213 
214 bool PopHelper::complete(WFVector *vec, int pos){
215 
216  assert(type == dt_popBack );
217 
218  PopSubHelper *psh=new PopSubHelper(this);
219 
220  ArrayElement *pb=vec->getSpot(pos-1);
221 
222  while (child.load() == NULL) {
223 
224  void *expected=pb->load();
225 
226  if (Helper::isHelper(expected)) {// TO BOUND
227 
228  Helper *tHelper=Helper::unmark(expected);
229  if(!tHelper->watch(expected, pb)){
230  continue;
231  }
232 
233  bool helpRes=Helper::remove(vec, pos-1, expected);
234 
235  tHelper->unwatch();
236 
237  if(!helpRes && rDepth>0){
238  psh->unsafeFree();
239  return false;
240  }
241  else {
242  continue;
243  }
244  }
245 
246 
247  if (expected==NOT_VALUE){
248  void *c_child=NULL;
249  if (child.compare_exchange_strong(c_child,(void *)0x1)){
250  break;
251  }
252  }
253  else {
254  psh->value=expected;
255  if (pb->compare_exchange_strong(expected, Helper::mark(psh))){
256  psh->complete(vec,pos-1);
257  break;
258  }
259  else {
260  continue;
261  }
262 
263  }
264  }//End While
265 
266  ArrayElement *pa=vec->getSpot(pos);
267 
268  void *temp=Helper::mark(this);
269  pa->compare_exchange_strong(temp, NOT_VALUE);
270 
271  if(child.load() != psh)
272  psh->safeFree();
273  return true;
274 
275 }
276 
277 
279  if(this->isWatched()){
280  return false;
281  }
282  else{
283  PopHelper *ph= assoc.load();
284  if (ph!=NULL && ph!=(PopHelper *)(0x1) ){
285  if(ph->isWatched() )
286  return false;
287 
288  PopSubHelper *pch=(PopSubHelper *)ph->child.load();
289  if(pch!=NULL && pch != (PopSubHelper *)0x1){
290  if (pch->isWatched()){
291  return false;
292  }
293  pch->unsafeFree();
294  }
295  ph->unsafeFree();
296  }
297 
298  this->unsafeFree();
299  return true;
300  }
301 }
302 
304 
305  if(this->isWatched()){
306  return false;
307  }
308  else{
309  PopHelper *op= (PopHelper *)(this);
310  PopSubHelper *t=(PopSubHelper *)(op->child.load());
311  if(t != NULL && t != (PopSubHelper *)0x1 ){
312  if(t->isWatched()){
313  return false;
314  }
315  else{
316  t->unsafeFree();
317  }
318  }
319  this->unsafeFree();
320  return true;
321 
322  }
323 }
325  if(this->isWatched()){
326  return false;
327  }
328  else{
329  this->unsafeFree();
330  return true;
331  }
332 }
void unwatch()
Definition: pop_helper.h:116
void * getValue()
Definition: pop_helper.h:133
void init(PopHelper *p)
Definition: pop_helper.h:71
bool getResult(void *&v)
Definition: pop_helper.h:191
std::atomic< void * > child
Definition: pop_helper.h:5
bool complete(WFVector *vec, int pos)
Definition: pop_helper.h:214
bool tryFree()
Definition: pop_helper.h:303
PopSubHelper(PopHelper *p)
Definition: pop_helper.h:79
Definition: pop_helper.h:66
PopHelper()
Definition: pop_helper.h:13
PopHelper * parent
Definition: pop_helper.h:69
void init(PopOp *cop)
Definition: pop_helper.h:7
void * value
Definition: pop_helper.h:68
PopHelper(PopOp *cop)
Definition: pop_helper.h:16
void * readThrough()
Definition: pop_helper.h:59
std::atomic< PopHelper * > assoc
Definition: pop_op.h:4
Definition: pop_helper.h:3
bool tryFree()
Definition: pop_helper.h:278
void unwatch()
Definition: pop_helper.h:48
void * readThrough()
Definition: pop_helper.h:127
bool isWatched()
Definition: pop_helper.h:123
bool watch(void *p, ArrayElement *a)
Definition: pop_helper.h:26
bool isWatched()
Definition: pop_helper.h:55
bool watch(void *p, ArrayElement *a)
Definition: pop_helper.h:87
bool tryFree()
Definition: pop_helper.h:324
PopOp * controlOp
Definition: pop_helper.h:6
Definition: pop_op.h:2
bool complete(WFVector *vec, int pos)
Definition: pop_helper.h:161