Tervel  1.0.0
A collection of wait-free containers and algorithms.
pushbackwra_op.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_PUSHWRA_OP_H
26 #define __TERVEL_CONTAINERS_WF_VECTOR_PUSHWRA_OP_H
27 
28 
29 #include <tervel/util/info.h>
30 #include <tervel/util/descriptor.h>
34 
35 
36 #include <tervel/containers/wf/vector/vector.hpp>
37 
38 namespace tervel {
39 namespace containers {
40 namespace wf {
41 namespace vector {
42 
43 template<typename T>
45 
46 
47 template<typename T>
49 public:
50  PushWRAOp(Vector<T> *vec, T val)
51  : vec_(vec)
52  , new_val_(val) {}
53 
55  PushWRAOpHelper<T> * temp = helper_.load();
56  assert(temp != nullptr);
58  }
59 
60  void help_complete() {
62 
64  PushWRAOpHelper<T> >(this);
65  T help_t = reinterpret_cast<T>(util::memory::rc::mark_first(helper));
66 
67  size_t placed_pos = vec_->size();
68  std::atomic<T> *spot = vec_->internal_array.get_spot(placed_pos);
69  T current = spot->load();
70 
71  while (helper_.load() == nullptr) {
72  if (current == Vector<T>::c_not_value_) {
73 
74  helper->set_idx(placed_pos);
75  if (!spot->compare_exchange_strong(current, help_t)) {
76  continue;
77  }
78  helper->complete(reinterpret_cast<void *>(help_t),
79  reinterpret_cast< std::atomic<void *> *>(spot));
80 
81  assert(helper_.load() == helper);
82  return;
83  } else if (vec_->internal_array.is_descriptor(current, spot)) {
84  continue;
85  } else { // its a valid value
86  placed_pos++;
87  spot = vec_->internal_array.get_spot(placed_pos);
88  current = spot->load();
89  }
90  }
92 
93 
94  };
95 
96  uint64_t result() {
97  PushOpHelper<T> *temp = helper_.load();
98  assert(temp != nullptr);
99  return temp->idx();
100  }
101 
102 private:
103  friend class PushWRAOpHelper<T>;
104  Vector<T> *vec_;
106  std::atomic<PushWRAOpHelper<T> *> helper_ {nullptr};
107 
108 }; // class PushWRAOp
109 
110 
111 template<typename T>
112 class PushWRAOpHelper: public tervel::util::Descriptor {
113 public:
115  : op_(op)
116  {}
117 
118  void set_idx(uint64_t i) {
119  idx_ = i;
120  };
121 
122  uint64_t idx() {
123  return idx_;
124  };
125 
126  bool result() {
127  if (op_->helper_.load() == nullptr) {
128  return associate();
129  } else if (op_->helper_.load() == this) {
130  return true;
131  } else {
132  assert(op_->helper_.load() != nullptr);
133  return false;
134  }
135  };
136 
137  bool associate() {
138  PushWRAOpHelper *temp_null = nullptr;
139  bool res = op_->helper_.compare_exchange_strong(temp_null, this);
140  if (res || temp_null == this) {
141  assert(op_->helper_.load() == this);
142  return true;
143  } else {
144  assert(false);
145  return false;
146  }
147  };
148 
150  void * complete(void *value, std::atomic<void *> *address) {
151  std::atomic<T> * spot = reinterpret_cast<std::atomic<T> *>(address);
152  bool op_res = associate();
153  T new_current = reinterpret_cast<T>(util::memory::rc::mark_first(this));
154  assert(reinterpret_cast<T>(value) == new_current);
155 // if (op_res) {
156  if (spot->compare_exchange_strong(new_current, op_->new_val_)) {
157  new_current = op_->new_val_;
158  }
159  //SEE: associate()
160 /* } else {
161  if (spot->compare_exchange_strong(new_current,
162  reinterpret_cast<T>(Vector<T>::c_not_value_))) {
163  new_current = reinterpret_cast<T>(Vector<T>::c_not_value_);
164  }
165  }*/
166  return reinterpret_cast<void *>(new_current);
167  } // complete
168 
170  void * get_logical_value() {
171  return reinterpret_cast<void *>(op_->new_val_);
172  } // get_logical_value
173 
183  bool on_watch(std::atomic<void *> *address, void * value) {
186  t_SlotID::SHORTUSE, op_, address, value);
187 
188  if (success) {
189  complete(value, address);
190  }
191  return false;
192  };
193 
194 private:
195  friend class PushWRAOp<T>;
197  uint64_t idx_;
198 // std::atomic<uint64_t> success_ {0};
199 
200 }; // class PushWRAOpHelper
201 
202 } // namespace vector
203 } // namespace wf
204 } // namespace containers
205 } // namespace tervel
206 #endif // __TERVEL_CONTAINERS_WF_VECTOR_PUSHWRA_OP_H
DescrType * get_descriptor(Args &&...args)
Constructs and returns a descriptor.
Definition: descriptor_util.h:50
virtual void * get_logical_value()=0
This method is implemented by each sub class.
void help_complete()
Implementations of this function that upon its return the operation described in the OpRecord has bee...
Definition: pushbackwra_op.h:60
uint64_t idx()
Definition: pushbackwra_op.h:122
~PushWRAOp()
Definition: pushbackwra_op.h:54
__thread void * tl_control_word
PushWRAOp(Vector< T > *vec, T val)
Definition: pushbackwra_op.h:50
uint64_t idx()
Definition: pushback_op.h:311
void * mark_first(tervel::util::Descriptor *descr)
This returns the passed reference with its least signifcant bit set to 1.
Definition: descriptor_util.h:157
void free_descriptor(tervel::util::Descriptor *descr, bool dont_check=false)
Once a user is done with a descriptor, they should free it with this method.
Definition: descriptor_util.h:65
TODO(steven):
Definition: mcas.h:36
std::atomic< PushWRAOpHelper< T > * > helper_
Definition: pushbackwra_op.h:106
Definition: pushbackwra_op.h:48
This defines the Descriptor class, this class is designed to be extend and be used in conjunction wit...
Definition: descriptor.h:60
static bool watch(SlotID slot_id, Element *elem, std::atomic< void * > *address, void *expected, HazardPointer *const hazard_pointer=tervel::tl_thread_info->get_hazard_pointer())
This method is used to achieve a hazard pointer watch on the the based descr.
virtual void * complete(void *current, std::atomic< void * > *address)=0
This method is implemented by each sub class and must guarantee that upon return that the descriptor ...
bool result()
Definition: pushbackwra_op.h:126
This class is used to create Operation Records.
Definition: progress_assurance.h:52
void * complete(void *value, std::atomic< void * > *address)
This method is implemented by each sub class and must guarantee that upon return that the descriptor ...
Definition: pushbackwra_op.h:150
uint64_t idx_
Definition: pushbackwra_op.h:197
uint64_t result()
Definition: pushbackwra_op.h:96
virtual bool on_watch(std::atomic< void * > *, void *)
This method is optional to implement for each sub class.
Definition: descriptor.h:99
void * get_logical_value()
This method is implemented by each sub class.
Definition: pushbackwra_op.h:170
PushWRAOpHelper(PushWRAOp< T > *op)
Definition: pushbackwra_op.h:114
bool on_watch(std::atomic< void * > *address, void *value)
This method is optional to implement for each sub class.
Definition: pushbackwra_op.h:183
Vector< T > * vec_
Definition: pushbackwra_op.h:104
T new_val_
Definition: pushbackwra_op.h:105
void set_idx(uint64_t i)
Definition: pushbackwra_op.h:118
bool associate()
Definition: pushbackwra_op.h:137
PushWRAOp< T > * op_
Definition: pushbackwra_op.h:196
SlotID
Definition: hazard_pointer.h:58