25 #ifndef TERVEL_MCAS_MCAS_IMP_H_
26 #define TERVEL_MCAS_MCAS_IMP_H_
30 namespace algorithms {
41 }
else if (row_count_ == max_rows_) {
44 cas_rows_[row_count_].address_ = address;
45 cas_rows_[row_count_].expected_value_ = expected_value;
46 cas_rows_[row_count_].new_value_ = new_value;
47 cas_rows_[row_count_++].helper_.store(
nullptr);
51 for (
int i = (row_count_ - 1); i > 0; i--) {
52 if (cas_rows_[i] > cas_rows_[i-1]) {
53 swap(cas_rows_[i], cas_rows_[i-1]);
54 }
else if (cas_rows_[i] == cas_rows_[i-1]) {
55 for (; i < row_count_-1; i++) {
56 swap(cas_rows_[i], cas_rows_[i+1]);
61 cas_rows_[row_count_].address_ =
nullptr;
62 cas_rows_[row_count_].expected_value_ =
nullptr;
63 cas_rows_[row_count_].new_value_ =
nullptr;
74 bool res = mcas_complete(0);
83 assert(cas_rows_[0].helper_.load() !=
nullptr);
84 assert(current_row->
helper_.load() !=
nullptr);
85 start_pos = current_row - &(cas_rows_[0]);
86 return mcas_complete(start_pos,
false);
95 for (
int pos = start_pos; pos < row_count_; pos++) {
100 assert(pos == 0 || cas_rows_[pos-1].helper_.load());
103 T current_value = row->
address_->load();
105 while (row->
helper_.load() ==
nullptr) {
108 if (state_.load() != MCasState::IN_PROGRESS) {
110 return (state_.load() == MCasState::PASS);
111 }
else if (!wfmode && progAssur.
isDelayed()) {
116 assert(state_.load() != MCasState::IN_PROGRESS);
117 return (state_.load() == MCasState::PASS);
128 reinterpret_cast<void *>(current_value))) {
130 current_value = this->mcas_remove(pos, current_value);
139 current_value = row->
address_->load();
150 if (row->
helper_.compare_exchange_strong(temp_null,
151 reinterpret_cast<
Helper<T> *>(MCAS_FAIL_CONST))
152 || temp_null ==
reinterpret_cast<Helper<T> *
>(MCAS_FAIL_CONST)) {
154 MCasState temp_state = MCasState::IN_PROGRESS;
155 this->state_.compare_exchange_strong(temp_state, MCasState::FAIL);
156 assert(this->state_.load() == MCasState::FAIL);
166 if (row->
address_->compare_exchange_strong(current_value,
169 Helper<T> * temp_null =
nullptr;
170 if (row->
helper_.compare_exchange_strong(temp_null, helper)
171 || temp_null == helper) {
178 T temp_helper =
reinterpret_cast<T
>(
181 row->
address_->compare_exchange_strong(temp_helper,
186 if(row->
helper_.load() ==
reinterpret_cast<Helper<T> *
>(
188 MCasState temp_state = MCasState::IN_PROGRESS;
189 this->state_.compare_exchange_strong(temp_state, MCasState::FAIL);
192 assert(state_.load() != MCasState::IN_PROGRESS);
193 return (state_.load() == MCasState::PASS);
205 if (row->
helper_.load() ==
reinterpret_cast<Helper<T> *
>(MCAS_FAIL_CONST)) {
206 MCasState temp_state = MCasState::IN_PROGRESS;
207 this->state_.compare_exchange_strong(temp_state, MCasState::FAIL);
208 assert(this->state_.load() == MCasState::FAIL);
214 MCasState temp_state = MCasState::IN_PROGRESS;
215 if (this->state_.compare_exchange_strong(temp_state, MCasState::PASS)) {
216 temp_state = MCasState::PASS;
218 assert(this->state_.load() != MCasState::IN_PROGRESS);
219 return (temp_state == MCasState::PASS);
224 std::atomic<void *> *address =
reinterpret_cast<std::atomic<void *>*
>(
225 cas_rows_[pos].address_);
227 reinterpret_cast<void *>(value));
231 reinterpret_cast<void *>(value));
243 if (this->cas_rows_[pos].helper_.load() !=
nullptr) {
244 return static_cast<T
>(
nullptr);
251 return reinterpret_cast<T
>(address->load());
256 for (
int pos = 0; pos < row_count_; pos++) {
260 assert(row->
helper_.load() !=
nullptr);
263 T marked_helper =
reinterpret_cast<T
>(
265 if (temp_helper ==
reinterpret_cast<Helper<T> *
>(MCAS_FAIL_CONST)) {
270 T cur_value = row->
address_->load();
271 if (cur_value == marked_helper) {
275 row->
address_->compare_exchange_strong(cur_value,
288 #endif // TERVEL_MCAS_MCAS_IMP_H_
DescrType * get_descriptor(Args &&...args)
Constructs and returns a descriptor.
Definition: descriptor_util.h:50
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
T mcas_remove(const int pos, T value)
This function insures that upon its return that *(cas_rows_[pos].address) no longer equals value...
Definition: mcas_imp.h:223
bool isValid(void *value)
Returns whether or not the passed value is has one of the reserved bits set to 1. ...
Definition: util.h:155
static bool is_watched(Element *descr, HazardPointer *const hazard_pointer=tervel::tl_thread_info->get_hazard_pointer())
This method is used to determine if a hazard pointer watch exists on a passed value.
This class is used to represent a one of the M CAS operations performed by an MCAS operation...
Definition: mcas_casrow.h:45
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
T expected_value_
Definition: mcas_casrow.h:85
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
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
bool add_cas_triple(std::atomic< T > *address, T expected_value, T new_value)
This function is used to add a CAS triple to the MCAS operation.
Definition: mcas_imp.h:35
MCasState
This enum is used to indicate the state of an mcas operation DELETED is used in debugging procedures...
Definition: mcas.h:143
bool execute()
This function is called after all the CAS triples have been added to the operation.
Definition: mcas_imp.h:72
std::atomic< T > * address_
Definition: mcas_casrow.h:82
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
std::atomic< Helper< T > * > helper_
Definition: mcas_casrow.h:87
static bool recursive_return(bool change=false, bool value=false)
bool mcas_complete(int start_pos, bool wfmode=false)
This function is used to complete a currently executing MCAS operation It is most likely that this op...
Definition: mcas_imp.h:90
static size_t recursive_depth(size_t i=0)
Adds the passed value and returns the pre-incremented value.
void cleanup(bool success)
This function is used to cleanup a completed MCAS operation It removes each MCH placed during this op...
Definition: mcas_imp.h:255
This defines the Descriptor class, this class is designed to be extend and be used in conjunction wit...
Definition: descriptor.h:60
tervel::util::Descriptor * unmark_first(void *descr)
This returns an unbitmarked reference.
Definition: descriptor_util.h:178
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
bool is_descriptor_first(void *descr)
This returns whether or not the least significant bit holds a bitmark.
Definition: descriptor_util.h:189
T new_value_
Definition: mcas_casrow.h:86
static void set_recursive_return()
Definition: recursive_action.h:57
This class is the MCAS operation's helper.
Definition: mcas_casrow.h:37
void * remove_descriptor(void *expected, std::atomic< void * > *address)
This method is used to remove a descriptor object that is conflict with another threads operation...
Definition: descriptor_util.h:208
bool isDelayed(size_t val=1)
Definition: progress_assurance.h:125
static void clear_recursive_return()
Definition: recursive_action.h:61
Definition: progress_assurance.h:120