Tervel  1.0.0
A collection of wait-free containers and algorithms.
vector_imp.h
Go to the documentation of this file.
1 /*
2 The MIT License (MIT)
3 
4 Copyright (c) 2015 University of Central Florida's Computer Software Engineering
5 Scalable & Secure Systems (CSE - S3) Lab
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 THE SOFTWARE.
24 */
25 #ifndef __TERVEL_CONTAINERS_WF_VECTOR_VECTOR_IMP_
26 #define __TERVEL_CONTAINERS_WF_VECTOR_VECTOR_IMP_
27 
28 #include <tervel/util/info.h>
29 #include <tervel/util/descriptor.h>
30 
31 #include <tervel/containers/wf/vector/vector.hpp>
33 
40 
41 
42 
43 namespace tervel {
44 namespace containers {
45 namespace wf {
46 namespace vector {
47 
48 template<typename T>
49 size_t Vector<T>::push_back_only(T value) {
50  if (!internal_array.is_valid(value)) {
51  assert(false);
52  return -1;
53  }
54 
55  size_t placed_pos = size(1);
56  std::atomic<T> *spot = internal_array.get_spot(placed_pos);
57 
58  spot->store(value, std::memory_order_relaxed);
59  return placed_pos;
60 } // push_back_only
61 
62  template<typename T>
63  size_t Vector<T>::push_back_w_ra(T value) {
65 
66  if (!internal_array.is_valid(value)) {
67  assert(false);
68  return -1;
69  }
70 
71  size_t placed_pos = size();
72 
73 
75  while (progAssur.isDelayed()) {
76  std::atomic<T> *spot = internal_array.get_spot(placed_pos);
77  T expected = spot->load();
78  if ( (expected == Vector<T>::c_not_value_) &&
79  spot->compare_exchange_weak(expected, value) ) {
80  size(1);
81  return placed_pos;
82  } else if (internal_array.is_descriptor(expected, spot)) {
83  continue;
84  } else { // its a valid value
85  placed_pos++;
86  }
87  }
88 
89  PushWRAOp<T> *op = new PushWRAOp<T>(this, value);
91  reinterpret_cast<tervel::util::OpRecord *>(op));
92 
93  size_t result = op->result(value);
94  op->safe_delete();
95 
96  return result;
97  } // push_back_w_ra
98 
99 template<typename T>
100 bool Vector<T>::pop_back_only(T &value) {
101  size_t poped_pos = size(-1);
102 
103  if (poped_pos <= 0) {
104  size(1);
105  return false;
106  } else {
107  std::atomic<T> *spot = internal_array.get_spot(poped_pos);
108  value = spot->load(std::memory_order_relaxed);
109  spot->store(Vector<T>::c_not_value_, std::memory_order_relaxed);
110 
111  return true;
112  }
113 } // pop_back_only
114 
115 
116  template<typename T>
117  bool Vector<T>::pop_back_w_ra(T &value) {
119 
120  size_t poped_pos = size();
121 
122 
124  while (progAssur.isDelayed()) {
125  if (poped_pos <= 0) {
126  return false;
127  }
128 
129  // TODO(steven) after working, optimize the below load in the event the
130  // value changes
131  std::atomic<T> *spot = internal_array.get_spot(poped_pos - 1);
132  T current = spot->load();
133 
134  if (current == Vector<T>::c_not_value_) {
135  poped_pos--;
136  continue;
137  } else if (internal_array.is_descriptor(current, spot)) {
138  continue;
139  }else if (spot->compare_exchange_weak(current, Vector<T>::c_not_value_)) {
140  size(-1);
141  value = current;
142  return true;
143  } else {
144  poped_pos--;
145  }
146  }
147 
148  PopWRAOp<T> *op = new PopWRAOp<T>(this, value);
150  reinterpret_cast<tervel::util::OpRecord *>(op));
151 
152  bool result = op->result(value);
153  op->safe_delete();
154 
155  return result;
156  } // pop_back_w_ra
157 
158 
159 template<typename T>
160 size_t Vector<T>::push_back(T value) {
162 
163  if(!internal_array.is_valid(value)){
164  assert(false);
165  return -1;
166  }
167 
168  size_t pos = PushOp<T>::execute(this, value);
169 
170  size(1);
171  return pos;
172 }
173 
174 
175 template<typename T>
176 bool Vector<T>::pop_back(T &value) {
178 
179  bool res = PopOp<T>::execute(this, value);
180 
181  if (res) {
182  size(-1);
183  }
184  return res;
185 }
186 
187 template<typename T>
188 bool Vector<T>::at(size_t idx, T &value) {
190 
191  std::atomic<void *> control_address(nullptr);
192  tervel::tl_control_word = &control_address;
193 
194  if (idx < capacity()) {
195  std::atomic<T> *spot = internal_array.get_spot(idx, false);
196 
198  while (progAssur.isDelayed()) {
199  T cvalue = spot->load(std::memory_order_relaxed);
200 
201  if (cvalue == Vector<T>::c_not_value_) {
202  return false;
203  }else if (internal_array.is_descriptor(cvalue, spot)) {
204  continue;
205  } else {
206  assert(internal_array.is_valid(cvalue));
207  value = cvalue;
208  return true;
209  }
210  } // while fail threshold has not been reached
211 
212  ReadOp<T> *op = new ReadOp<T>(this, idx);
213 
214 
216  reinterpret_cast<tervel::util::OpRecord *>(op));
217 
218  bool op_succ = op->result(value);
219  op->safe_delete();
220 
221  return op_succ;
222  } // if idx < capacity()
223 
224  return false;
225 };
226 
227 template<typename T>
228 bool Vector<T>::cas(size_t idx, T &expected, const T val) {
229  assert(internal_array.is_valid(expected));
230  assert(internal_array.is_valid(val));
231 
233 
234  std::atomic<void *> control_address(nullptr);
235  tervel::tl_control_word = &control_address;
236 
237  if (idx < capacity()) {
238  std::atomic<T> *spot = internal_array.get_spot(idx, false);
239 
241  while (progAssur.isDelayed()) {
242  T cvalue = spot->load(std::memory_order_relaxed);
243 
244  if (cvalue == c_not_value_) {
245  return false;
246  } else if (internal_array.is_descriptor(cvalue, spot)) {
247  continue;
248  } else if (cvalue == expected) {
249  T temp = expected;
250  bool suc = spot->compare_exchange_strong(temp, val);
251  if (suc) {
252  return suc;
253  }
254  } else {
255  expected = cvalue;
256  return false;
257  }
258  } // while fail threshold has not been reached
259 
260  WriteOp<T> *op = new WriteOp<T>(this, idx, expected, val);
261 
263  reinterpret_cast<tervel::util::OpRecord *>(op));
264 
265  bool op_succ = op->result(expected);
266  op->safe_delete();
267 
268  return op_succ;
269  } // if idx < capacity()
270 
271  expected = Vector<T>::c_not_value_;
272  return false;
273 };
274 
275 /*
276 template<typename T>
277 bool Vector<T>::insertAt(int idx, T value){
278  tervel::util::ProgressAssurance::check_for_announcement();
279 
280  InsertAt<T>* op = new InsertAt<T>(idx, value);
281  tl_control_word = &(op->state);
282 
283  bool res=op->begin(this);
284 
285  if (res) {
286  op->cleanup(this, idx);
287  size(1);
288  }
289 
290  op->safe_delete();
291  return res;
292 };
293 
294 template<typename T>
295 bool Vector<T>::eraseAt(int idx, T &value){
296  tervel::util::ProgressAssurance::check_for_announcement();
297 
298  EraseAt<T>* op = new EraseAt<T>(idx);
299  tl_control_word = &(op->state);
300 
301  bool res=op->begin(this, value);
302 
303  if (res) {
304  op->cleanup(this, idx);
305  size(-1);
306  }
307 
308  op->safe_delete();
309  return res;
310 }; */
311 
312 } // namespace vector
313 } // namespace wf
314 } // namespace containers
315 } // namespace tervel
316 
317 #endif // __TERVEL_CONTAINERS_WF_VECTOR_VECTOR_IMP_
static void check_for_announcement(ProgressAssurance *const progress_assuarance=nullptr)
This function checks at most one position in the op_table_ for an OPRecod If one is found it will cal...
Definition: progress_assurance.h:151
static size_t execute(Vector< T > *vec, T val)
Definition: pushback_op.h:63
__thread void * tl_control_word
TODO(steven):
Definition: mcas.h:36
static bool execute(Vector< T > *vec, T &val)
Definition: popback_op.h:67
static void make_announcement(OpRecord *op, const uint64_t tid=tervel::tl_thread_info->get_thread_id(), ProgressAssurance *const prog_assur=tervel::tl_thread_info->get_progress_assurance())
This function places the.
Definition: progress_assurance.h:172
bool isDelayed(size_t val=1)
Definition: progress_assurance.h:125
Definition: progress_assurance.h:120