Tervel  1.0.0
A collection of wait-free containers and algorithms.
push_helper.h
Go to the documentation of this file.
1 
2 class PushHelper: public Helper{
3 public:
4  void *value;
5  std::atomic<long> pos;
7  void init(void *v, PushOp *op){
8  assert(sizeof(PushHelper) <= ALIGNLEN);
9  value=v;
10  pos=-1;
11  type=dt_pushBack;
12  controlOp=op;
13  };
14 
15  PushHelper(void *v){
16  init(v, NULL);
17  };
18 
19  PushHelper(void *v, PushOp *op){
20  init(v,op);
21  };
22 
23 
24 
25  bool complete(WFVector *vec, int pos);
26  bool tryFree();
27 
28  bool watch(void *p, ArrayElement *a){
29 
30  rc_count.fetch_add(1);
31 
32  if (a->load() != p){
33  rc_count.fetch_add(-1);
34  return false;
35  }
36 
37 
38  if (controlOp){
39  controlOp->rc_count.fetch_add(1);
40  if (a->load() != p){
41  rc_count.fetch_add(-1);
42  controlOp->rc_count.fetch_add(-1);
43  return false;
44  }
45  }
46 
47  return true;
48  };
49 
50  void unwatch(){
51  rc_count.fetch_add(-1);
52 
53  if (controlOp){
54  controlOp->rc_count.fetch_add(-1);
55  }
56  };
57  bool isWatched(){
58  return (rc_count.load() !=0);
59  };
60 
61  void * readThrough(){
62  if(pos.load() >= 0){
63  return value;
64  }
65  else{
66  return NOT_VALUE;
67  }
68  };
69 
70 };
71 
72 
73 bool PushHelper::complete(WFVector *vec, int pos){
74  assert(type == dt_pushBack);
75 
76  ArrayElement *pA=vec->getSpot(pos);
77  ArrayElement *pB=vec->getSpot(pos-1);
78 
79  long spos=this->pos.load();
80  while (this->pos.load() == -1) {
81 
82  if (fcount++ == MAX_FAILURES){
83  if(rDepth > 0){
84  return false;
85  }
86 
87  this->pos.compare_exchange_strong(spos, -2);
88  break;
89  }
90 
91  void *expected=pB->load();
92 
93  if (Helper::isHelper(expected)) {
94  Helper *tHelper=Helper::unmark(expected);
95 
96  if (!tHelper->watch(expected, pB)) {
97  continue;
98  }
99  bool helpRes = Helper::remove(vec, pos-1, expected);
100  tHelper->unwatch();
101 
102  if (!helpRes && rDepth>0) {
103  return false;
104  }
105  else{
106  continue;
107  }
108  }
109 
110  assert(!Helper::isHelper(expected));
111  if (expected == NOT_VALUE) {
112  this->pos.compare_exchange_strong(spos, -2);
113  }
114  else{
115  this->pos.compare_exchange_strong(spos, pos);
116  }
117  break;
118 
119  }
120  spos=this->pos.load();
121  assert(spos != -1);
122 
123  PushOp *op=this->controlOp;
124  PushHelper *temp=NULL;
125  void *expected=Helper::mark(this);
126 
127  if(spos== -2){
128  pA->compare_exchange_strong(expected, NOT_VALUE);
129  }
130  else if(op == NULL){
131  pA->compare_exchange_strong(expected, value);
132  }
133  else if (op->assoc.compare_exchange_strong(temp, this) || temp==this){
134  pA->compare_exchange_strong(expected, value);
135  }
136  else{
137  pA->compare_exchange_strong(expected, NOT_VALUE);
138  }
139 
140  return true;
141 
142 };
143 
145  if(this->isWatched()){
146  return false;
147  }
148  else{
149  this->unsafeFree();
150  return true;
151  }
152 }
Definition: push_helper.h:2
bool watch(void *p, ArrayElement *a)
Definition: push_helper.h:28
Definition: push_op.h:5
bool isWatched()
Definition: push_helper.h:57
void unwatch()
Definition: push_helper.h:50
bool complete(WFVector *vec, int pos)
Definition: push_helper.h:73
PushHelper(void *v, PushOp *op)
Definition: push_helper.h:19
PushHelper(void *v)
Definition: push_helper.h:15
PushOp * controlOp
Definition: push_helper.h:6
void * value
Definition: push_helper.h:4
bool tryFree()
Definition: push_helper.h:144
void init(void *v, PushOp *op)
Definition: push_helper.h:7
std::atomic< long > pos
Definition: push_helper.h:5
void * readThrough()
Definition: push_helper.h:61