25 #ifndef __TERVEL_CONTAINERS_WF_VECTOR_POP_OP_H
26 #define __TERVEL_CONTAINERS_WF_VECTOR_POP_OP_H
36 #include <tervel/containers/wf/vector/vector.hpp>
39 namespace containers {
60 assert(temp !=
nullptr);
67 static bool execute(Vector<T> *vec, T &val) {
68 size_t placed_pos = vec->size();
69 if (placed_pos == 0) {
78 std::atomic<T> *spot = vec->internal_array.get_spot(placed_pos);
80 T current = spot->load();
84 if (current == Vector<T>::c_not_value_) {
87 helper->
set_prev_spot(vec->internal_array.get_spot(placed_pos-1));
88 if (!spot->compare_exchange_strong(current, help_t)) {
91 helper->
complete(reinterpret_cast<void *>(help_t),
92 reinterpret_cast< std::atomic<void *> *
>(spot));
93 bool op_res = helper->
result(val);
100 if (placed_pos == 0) {
110 spot = vec->internal_array.get_spot(placed_pos);
111 current = spot->load();
113 }
else if (vec->internal_array.is_descriptor(current, spot)) {
117 spot = vec->internal_array.get_spot(placed_pos);
118 current = spot->load();
129 bool op_res = op->
result(val);
137 assert(temp !=
nullptr);
147 assert(temp !=
nullptr);
157 if (temp ==
nullptr) {
163 size_t placed_pos =
vec_->size();
164 if (placed_pos == 0) {
175 std::atomic<T> *spot = vec_->internal_array.get_spot(placed_pos);
176 T current = spot->load();
178 while (
helper_.load() ==
nullptr) {
179 if (current == Vector<T>::c_not_value_) {
183 helper->
set_prev_spot(vec_->internal_array.get_spot(placed_pos-1));
185 if (!spot->compare_exchange_strong(current, help_t)) {
188 helper->
complete(reinterpret_cast<void *>(help_t),
189 reinterpret_cast< std::atomic<void *> *
>(spot));
191 bool op_res = helper->
result();
198 if (placed_pos == 0) {
209 spot = vec_->internal_array.get_spot(placed_pos);
210 current = spot->load();
212 }
else if (vec_->internal_array.is_descriptor(current, spot)) {
216 spot = vec_->internal_array.get_spot(placed_pos);
217 current = spot->load();
227 if (temp ==
nullptr) {
230 }
else if (this->is_failed()) {
240 std::atomic<PopOpHelper<T> *>
helper_ {
nullptr};
259 if (temp ==
nullptr) {
261 }
else if (temp == fail_const) {
274 return child_.load() ==
nullptr;
279 assert(temp !=
nullptr);
280 if (temp == fail_const) {
290 assert(temp !=
nullptr);
291 if (temp == fail_const) {
300 if (temp ==
nullptr) {
301 child_.compare_exchange_strong(temp, fail_const);
308 return reinterpret_cast<void *
>(Vector<T>::c_not_value_);
312 void *
complete(
void *value, std::atomic<void *> *address) {
313 std::atomic<T> * spot =
reinterpret_cast<std::atomic<T> *
>(address);
321 while (in_progress()) {
322 if (progAssur.
isDelayed() || current_prev == Vector<T>::c_not_value_) {
325 }
else if (
vec_->internal_array.is_descriptor(current_prev,
prev_spot_)) {
332 if (
prev_spot_->compare_exchange_strong(current_prev, child_m)) {
333 child->
complete(reinterpret_cast<void *>(child_m),
334 reinterpret_cast<std::atomic<void *> *
>(
prev_spot_));
336 if (child_.load() != child) {
347 if (spot->compare_exchange_strong(help_t,
348 reinterpret_cast<T>(Vector<T>::c_not_value_))) {
349 return reinterpret_cast<void *
>(Vector<T>::c_not_value_);
351 return reinterpret_cast<void *
>(help_t);
357 if (cur_child ==
nullptr) {
358 if (child_.compare_exchange_strong(cur_child, child)) {
363 if (cur_child != child) {
367 if (op_ ==
nullptr) {
372 bool res = op_->helper_.compare_exchange_strong(temp_null,
this);
373 if (res || temp_null ==
this) {
374 assert(op_->helper_.load() ==
this);
377 assert(op_->helper_.load() !=
this);
391 bool on_watch(std::atomic<void *> *address,
void * value) {
392 if (op_ ==
nullptr) {
397 t_SlotID::SHORTUSE, op_, address, value);
404 if (op_ !=
nullptr) {
413 assert(temp !=
nullptr);
414 if (temp == fail_const) {
430 std::atomic<PopOpSubHelper<T> *> child_ {
nullptr};
446 return reinterpret_cast<void *
>(Vector<T>::c_not_value_);
450 void *
complete(
void *value, std::atomic<void *> *address) {
453 bool is_valid = parent_->associate(
this);
457 new_val =
reinterpret_cast<void *
>(Vector<T>::c_not_value_);
459 new_val =
reinterpret_cast<void *
>(val_);
462 if (address->compare_exchange_strong(value, new_val)) {
478 bool on_watch(std::atomic<void *> *address,
void * value) {
481 complete(value, address);
498 #endif // __TERVEL_CONTAINERS_WF_VECTOR_POP_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.
__thread void * tl_control_word
virtual void on_unwatch()
This method must be implemented if on_watch is implemented, and is optional otherwise.
Definition: descriptor.h:109
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 * 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: popback_op.h:312
bool on_watch(std::atomic< void * > *address, void *value)
This method is optional to implement for each sub class.
Definition: popback_op.h:391
Vector< T > * vec_
Definition: popback_op.h:238
~PopOpHelper()
Definition: popback_op.h:257
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
void set_failed()
Definition: popback_op.h:155
bool result()
Definition: popback_op.h:145
TODO(steven):
Definition: mcas.h:36
void unwatch(tervel::util::Descriptor *descr)
This method is used to decrement the reference count of the passed descriptor object.
Definition: descriptor_util.h:139
std::atomic< T > * prev_spot_
Definition: popback_op.h:239
void * get_logical_value()
This method is implemented by each sub class.
Definition: popback_op.h:445
void set_control_word()
Definition: popback_op.h:421
PopOpHelper(Vector< T > *vec, PopOp< T > *op)
Definition: popback_op.h:249
bool result(T &val)
Definition: popback_op.h:135
virtual bool on_is_watched()
This method is optional to implement for each sub class.
Definition: descriptor.h:117
bool result()
Definition: popback_op.h:288
static bool execute(Vector< T > *vec, T &val)
Definition: popback_op.h:67
PopOpHelper< T > * parent_
Definition: popback_op.h:490
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 is_watched(tervel::util::Descriptor *descr)
This method is used to determine if the passed descriptor is under rc protection. ...
Definition: descriptor_util.h:78
void set_prev_spot(std::atomic< T > *prev_spot)
Definition: popback_op.h:269
PopOpSubHelper(PopOpHelper< T > *parent, T val)
Definition: popback_op.h:436
This defines the Descriptor class, this class is designed to be extend and be used in conjunction wit...
Definition: descriptor.h:60
static void unwatch(SlotID slot_id, HazardPointer *const hazard_pointer=tervel::tl_thread_info->get_hazard_pointer())
This method is used to remove the hazard pointer watch.
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 ...
void safe_delete(bool no_check=false, ElementList *const element_list=tervel::tl_thread_info->get_hp_element_list())
This function is used to free a hazard pointer protected object if it is safe to do so OR add it to a...
Definition: hp_element.h:67
bool is_watched()
Definition: popback_op.h:224
bool watch(tervel::util::Descriptor *descr, std::atomic< void * > *address, void *value)
This method is used to increment the reference count of the passed descriptor object.
Definition: descriptor_util.h:105
This class is used to create Operation Records.
Definition: progress_assurance.h:52
PopOp(Vector< T > *vec)
Definition: popback_op.h:55
Definition: popback_op.h:44
bool on_watch(std::atomic< void * > *address, void *value)
This method is optional to implement for each sub class.
Definition: popback_op.h:478
Vector< T > * vec_
Definition: popback_op.h:427
Definition: popback_op.h:47
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: popback_op.h:307
~PopOp()
Definition: popback_op.h:58
void val(T &val)
Definition: popback_op.h:440
void help_complete()
Implementations of this function that upon its return the operation described in the OpRecord has bee...
Definition: popback_op.h:162
Definition: popback_op.h:51
void fail()
Definition: popback_op.h:298
bool in_progress()
Definition: popback_op.h:273
bool isDelayed(size_t val=1)
Definition: progress_assurance.h:125
std::atomic< PopOpHelper< T > * > helper_
Definition: popback_op.h:240
Definition: progress_assurance.h:120
PopOpHelper(Vector< T > *vec)
Definition: popback_op.h:253
bool on_is_watched()
This method is optional to implement for each sub class.
Definition: popback_op.h:411
static constexpr PopOpHelper< T > * is_empty_const
Definition: popback_op.h:53
bool associate(PopOpSubHelper< T > *child)
Definition: popback_op.h:355
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: popback_op.h:450
void on_unwatch()
This method must be implemented if on_watch is implemented, and is optional otherwise.
Definition: popback_op.h:403
bool result(T &val)
Definition: popback_op.h:277
SlotID
Definition: hazard_pointer.h:58