25 #ifndef TERVEL_CONTAINER_WF_HASH_MAP_WFHM_HASHMAP_H
26 #define TERVEL_CONTAINER_WF_HASH_MAP_WFHM_HASHMAP_H
44 namespace containers {
50 template<
class Key,
class Value>
74 template<
class Key,
class Value,
class Functor = default_functor<Key, Value> >
79 HashMap(uint64_t capacity, uint64_t expansion_rate = 3)
98 if (temp !=
nullptr) {
120 bool at(Key key, ValueAccessor &va);
144 bool remove(Key key);
269 for (
size_t i = 0; i <
len_; i++) {
278 for (
size_t i = 0; i <
len_; i++) {
280 if (temp !=
nullptr) {
292 assert(pos < len_ && pos >=0);
367 }
else if (value ==
nullptr || value->
is_data()) {
369 value =
loc_->load();
414 template<
class Key,
class Value,
class Functor>
417 std::atomic<void *> *temp_address =
418 reinterpret_cast<std::atomic<void *> *
>(loc);
420 void * temp = temp_address->load();
422 if (temp ==
nullptr) {
429 temp, temp_address, temp);
432 value =
reinterpret_cast<Node *
>(temp);
437 template<
class Key,
class Value,
class Functor>
445 template<
class Key,
class Value,
class Functor>
449 key = functor.hash(key);
452 uint64_t position = get_position(key, depth);
453 Location *loc = &(primary_array_[position]);
464 reinterpret_cast<tervel::util::OpRecord *>(op));
469 if (!hp_watch_and_get_value(loc, curr_value)) {
471 }
else if (curr_value ==
nullptr) {
473 }
else if (curr_value->
is_array()) {
476 position = get_position(key, depth);
477 loc = array_node->
access(position);
483 if (functor.key_equals(data_node->key_, key)) {
486 va.
init(&(data_node->value_), &(data_node->access_count_));
489 data_node->access_count_.fetch_add(-1);
502 template<
class Key,
class Value,
class Functor>
508 key = functor.hash(key);
514 uint64_t position = get_position(key, depth);
516 Location *loc = &(primary_array_[position]);
529 if (!hp_watch_and_get_value(loc, curr_value)) {
531 }
else if (curr_value ==
nullptr) {
532 if (loc->compare_exchange_strong(curr_value, new_node)) {
537 }
else if (curr_value->
is_array()) {
540 position = get_position(key, depth);
541 loc = array_node->
access(position);
546 if (data_node->access_count_.load() < 0) {
547 if (loc->compare_exchange_strong(curr_value, new_node)) {
549 data_node->safe_delete();
554 }
else if (functor.key_equals(data_node->key_, key)) {
559 expand_map(loc, curr_value, depth);
567 assert(loc->load() != new_node);
574 template<
class Key,
class Value,
class Functor>
578 key = functor.hash(key);
581 uint64_t position = get_position(key, depth);
583 Location *loc = &(primary_array_[position]);
599 if (!hp_watch_and_get_value(loc, curr_value)) {
601 }
else if (curr_value ==
nullptr) {
604 }
else if (curr_value->
is_array()) {
607 position = get_position(key, depth);
608 loc = array_node->
access(position);
613 int64_t temp_expected = 0;
614 if (functor.key_equals(data_node->key_, key) &&
615 data_node->access_count_.compare_exchange_strong(temp_expected,
621 if (loc->compare_exchange_strong(curr_value,
nullptr)) {
622 assert(loc->load() != data_node);
623 assert(data_node->access_count_.load() < 0);
625 data_node->safe_delete();
640 template<
class Key,
class Value,
class Functor>
644 uint64_t next_position = 0;
647 if (curr_value !=
nullptr) {
650 next_position = get_position(data_node->key_, depth+1);
651 array_node->
access(next_position)->store(curr_value);
655 if (loc->compare_exchange_strong(curr_value, array_node)) {
658 assert(loc->load() != array_node);
659 array_node->
access(next_position)->store(
nullptr);
664 template<
class Key,
class Value,
class Functor>
667 const uint64_t *long_array =
reinterpret_cast<uint64_t *
>(&key);
668 const size_t max_length =
sizeof(Key) / (64 / 8);
670 assert(depth <= max_depth());
673 assert(primary_array_pow_ < 64);
675 uint64_t position = long_array[0] >> (64 - primary_array_pow_);
677 assert(position < primary_array_size_);
680 const int start_bit_offset = (depth-1)*secondary_array_pow_ +
682 const int end_bit_offset = (depth)*secondary_array_pow_ +
685 const size_t start_idx = start_bit_offset / 64;
686 const size_t start_idx_offset = start_bit_offset % 64;
687 const size_t end_idx = end_bit_offset / 64;
688 const size_t end_idx_offset = end_bit_offset % 64;
690 assert(start_idx == end_idx || start_idx + 1 == end_idx);
691 assert(end_idx <= max_length);
695 if (start_idx == end_idx) {
696 uint64_t value = long_array[start_idx];
697 value = value << start_idx_offset;
698 value = value >> (64 - secondary_array_pow_);
700 assert(value < secondary_array_size_);
703 uint64_t value = long_array[start_idx];
704 value = value << start_idx_offset;
705 value = value >> (64 - secondary_array_pow_ + end_idx_offset);
706 value = value << (end_idx_offset);
710 if (end_idx == max_length) {
713 value2 = long_array[end_idx];
715 value2 = value2 >> (64 - end_idx_offset);
717 uint64_t position = (value | value2);
718 assert(position < secondary_array_size_);
724 template<
class Key,
class Value,
class Functor>
727 uint64_t max_depth =
sizeof(Key)*8;
728 max_depth -= primary_array_pow_;
729 max_depth = std::ceil(max_depth / secondary_array_pow_);
735 template<
class Key,
class Value,
class Functor>
738 size_t max_depth_ = max_depth();
739 std::cout <<
"K(" << key <<
") :";
740 for (
size_t i = 0; i <= max_depth_; i++) {
741 uint64_t temp = get_position(key, i);
742 std::cout << temp <<
"-";
744 std::cout <<
"\n" << std::endl;
751 #endif // TERVEL_CONTAINER_WF_HASH_MAP_WFHM_HASHMAP_H
uint64_t len_
Definition: wf_hash_map.h:311
This class is used to safe guard access to values.
Definition: wf_hash_map.h:159
const size_t secondary_array_size_
Definition: wf_hash_map.h:406
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
Location * access(uint64_t pos)
Definition: wf_hash_map.h:291
void init(Value *value, std::atomic< int64_t > *access_count)
Initializes the value accessor.
Definition: wf_hash_map.h:202
Key hash(Key k)
Definition: wf_hash_map.h:52
uint64_t get_position(Key &key, size_t depth)
Definition: wf_hash_map.h:666
void expand_map(Location *loc, Node *curr_value, size_t depth)
Increases the capacity of the hash map by replacing a data node reference with a reference to an arra...
Definition: wf_hash_map.h:642
virtual ~Node()
Definition: wf_hash_map.h:248
void hp_unwatch()
Definition: wf_hash_map.h:439
size_t depth_
Definition: wf_hash_map.h:380
bool hp_watch_and_get_value(Location *loc, Node *&value)
This is a wrapper for hazard pointers.
Definition: wf_hash_map.h:416
TODO(steven): add description TODO(steven): move into a file.
Definition: wf_hash_map.h:352
~ValueAccessor()
Definition: wf_hash_map.h:166
size_t size()
Definition: wf_hash_map.h:149
bool remove(Key key)
Attempts to remove a key/value pair from the hash map Returns false in the event the key is not in th...
Definition: wf_hash_map.h:576
const size_t primary_array_pow_
Definition: wf_hash_map.h:405
TODO(steven):
Definition: mcas.h:36
bool is_array()
Definition: wf_hash_map.h:299
Node()
Definition: wf_hash_map.h:247
void reset()
Resets this value accessors, decrementing the access_count and clearing the variables.
Definition: wf_hash_map.h:188
HashMap(uint64_t capacity, uint64_t expansion_rate=3)
Definition: wf_hash_map.h:79
A default Functor implementation.
Definition: wf_hash_map.h:51
bool is_data()
Definition: wf_hash_map.h:338
bool key_equals(Key a, Key b)
Definition: wf_hash_map.h:56
Location * loc_
Definition: wf_hash_map.h:379
HashMap * map_
Definition: wf_hash_map.h:378
Key key_
Definition: wf_hash_map.h:342
This class is used for the creation of Hazard Pointer Protected Objects Objects which extend it have ...
Definition: hp_element.h:53
Value * value_
Definition: wf_hash_map.h:212
bool is_array()
Definition: wf_hash_map.h:331
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
int round_to_next_power_of_two(uint64_t value)
Returns the next power of two.
Definition: wf_hash_map_no_delete.h:44
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
const uint64_t get_num_threads()
~ArrayNode()
See Notes on hash map destructor.
Definition: wf_hash_map.h:277
bool insert(Key key, Value value)
This function returns true if the key value pair was successfully inserted.
Definition: wf_hash_map.h:504
This class is used to differentiate between data_nodes and array_nodes/.
Definition: wf_hash_map.h:245
__thread ThreadContext * tl_thread_info
Value * value()
Definition: wf_hash_map.h:173
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.
DataNode(Key k, Value v)
Definition: wf_hash_map.h:321
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.
const size_t secondary_array_pow_
Definition: wf_hash_map.h:407
~DataNode()
Definition: wf_hash_map.h:326
const size_t primary_array_size_
Definition: wf_hash_map.h:404
std::atomic< int64_t > * access_count_
Definition: wf_hash_map.h:211
This class is used to create Operation Records.
Definition: progress_assurance.h:52
friend class Node
Definition: wf_hash_map.h:236
This class is used to hold a key and value pair.
Definition: wf_hash_map.h:319
std::atomic< int64_t > access_count_
Definition: wf_hash_map.h:344
~HashMap()
Not Thread Safe! May create a very large stack! Note: should implement a better way...
Definition: wf_hash_map.h:95
Value value_
Definition: wf_hash_map.h:343
uint64_t Value
Definition: testObject.h:59
This class is used to hold the secondary array structure.
Definition: wf_hash_map.h:264
bool valid()
Definition: wf_hash_map.h:180
void print_key(Key &key)
Outputs the positions a key belongs in at each depth.
Definition: wf_hash_map.h:737
ForceExpandOp(HashMap *map, Location *loc, size_t depth)
Definition: wf_hash_map.h:354
A wait-free hash map implementation.
Definition: wf_hash_map.h:75
bool is_data()
Definition: wf_hash_map.h:306
void help_complete()
Implementations of this function that upon its return the operation described in the OpRecord has bee...
Definition: wf_hash_map.h:359
std::unique_ptr< Location[]> primary_array_
Definition: wf_hash_map.h:411
bool isDelayed(size_t val=1)
Definition: progress_assurance.h:125
ArrayNode(uint64_t len)
Definition: wf_hash_map.h:266
std::unique_ptr< Location[]> internal_array_
Definition: wf_hash_map.h:312
Definition: progress_assurance.h:120
std::atomic< Node * > Location
Definition: wf_hash_map.h:239
uint64_t max_depth()
Definition: wf_hash_map.h:726
std::atomic< uint64_t > size_
Definition: wf_hash_map.h:409
ValueAccessor()
Definition: wf_hash_map.h:162
void reset(size_t limit=TERVEL_PROG_ASSUR_LIMIT)
Definition: progress_assurance.h:131
bool at(Key key, ValueAccessor &va)
This function returns true and initializes the passed ValueAccessor if the key exists in the hash map...
Definition: wf_hash_map.h:447
virtual bool is_array()=0