using namespace std;
-
-
/**
This header file declares and defines a simplified version of Cliff Click's
NonblockingHashMap. It contains all the necessary structrues and main
for (i = 0; i < _size; i++) {
hashes[i] = 0;
}
- _data[1].store(hashes, memory_order_relaxed);
// Init the data to Null slot
for (i = 2; i < real_size; i++) {
_data[i].store(NULL, memory_order_relaxed);
}
+ _data[1].store(hashes, memory_order_release);
}
~kvs_data() {
struct slot {
bool _prime;
- shared_ptr<void> _ptr;
+ void *_ptr;
- slot(bool prime, shared_ptr<void> ptr) {
+ slot(bool prime, void *ptr) {
_prime = prime;
_ptr = ptr;
}
-
};
code for the its object, and "int equals(TypeK anotherKey)" which is
used to judge equality.
TypeK and TypeV should define their own copy constructor.
- To make the memory management safe and similar to Cliff Click's Java
- implementation, we use shared_ptr instead of normal pointer in terms of the
- pointers that point to TypeK and TypeV.
*/
template<typename TypeK, typename TypeV>
class cliffc_hashtable {
*oldkvs, int idx, void *should_help) {
kvs_data *newkvs = _newkvs.load(memory_order_acquire);
// We're only here cause the caller saw a Prime
- if (copy_slot(topmap, idx, oldkvs, _newkvs))
+ if (copy_slot(topmap, idx, oldkvs, newkvs))
copy_check_and_promote(topmap, oldkvs, 1); // Record the slot copied
return (should_help == NULL) ? newkvs : topmap->help_copy(newkvs);
}
// Promote the new table to the current table
if (copyDone + workdone == oldlen &&
- topmap->_kvs.load(memory_order_acquire) == oldkvs)
- topmap->_kvs.compare_exchange_strong(oldkvs, _newkvs, memory_order_release,
+ topmap->_kvs.load(memory_order_acquire) == oldkvs) {
+ kvs_data *newkvs = _newkvs.load(memory_order_acquire);
+ topmap->_kvs.compare_exchange_strong(oldkvs, newkvs, memory_order_release,
memory_order_release);
+ }
}
bool copy_slot(cliffc_hashtable *topmap, int idx, kvs_data *oldkvs,
__sequential.equals_val(_Old_Val, __RET__)
@End
*/
- shared_ptr<TypeV> get(TypeK& key) {
+ TypeV* get(TypeK& key) {
void *key_ptr = (void*) new TypeK(key);
- slot *key_slot = new slot(false, shared_ptr<void>(key_ptr));
+ slot *key_slot = new slot(false, key_ptr);
int fullhash = hash(key_slot);
- slot *V = get_impl(this, _kvs, key_slot, fullhash);
+ kvs_data *kvs = _kvs.load(memory_order_acquire);
+ slot *V = get_impl(this, kvs, key_slot, fullhash);
if (V == NULL) return NULL;
assert (!is_prime(V));
- return static_pointer_cast<TypeV>(V->_ptr);
+ return (TypeV*) V->_ptr;
}
/**
__sequential.equals_val(__RET__, _Old_Val)
@End
*/
- shared_ptr<TypeV> put(TypeK& key, TypeV& val) {
+ TypeV* put(TypeK& key, TypeV& val) {
return putIfMatch(key, val, NO_MATCH_OLD);
}
__COND_SAT__ ? __RET__ == NULL : __sequential.equals_val(_Old_Val, __RET__)
@End
*/
- shared_ptr<TypeV> putIfAbsent(TypeK& key, TypeV& value) {
+ TypeV* putIfAbsent(TypeK& key, TypeV& value) {
return putIfMatch(key, val, TOMBSTONE);
}
__sequential.equals_val(__RET__, _Old_Val)
@End
*/
- shared_ptr<TypeV> remove(TypeK& key) {
+ TypeV* remove(TypeK& key) {
return putIfMatch(key, TOMBSTONE, NO_MATCH_OLD);
}
__sequential.equals_val(__RET__, _Old_Val)
@End
*/
- shared_ptr<TypeV> replace(TypeK& key, TypeV& val) {
+ TypeV* replace(TypeK& key, TypeV& val) {
return putIfMatch(key, val, MATCH_ANY);
}
static int hash(slot *key_slot) {
assert(key_slot != NULL && key_slot->_ptr != NULL);
- shared_ptr<TypeK> key = static_pointer_cast<TypeK>(key_slot->_ptr);
+ TypeK* key = (TypeK*) key_slot->_ptr;
int h = key->hashCode();
// Spread bits according to Cliff Click's code
h += (h << 15) ^ 0xffffcd7d;
int fullhash) {
// Caller should've checked this.
assert (K != NULL);
- shared_ptr<TypeK> key_ptr = static_pointer_cast<TypeK>(key_slot->_ptr);
+ TypeK* key_ptr = (TypeK*) key_slot->_ptr;
return
K == key_slot ||
((hashes[hash] == 0 || hashes[hash] == fullhash) &&
static bool valeq(slot *val_slot1, slot *val_slot2) {
assert (val_slot1 != NULL);
- shared_ptr<TypeK> ptr1 = static_pointer_cast<TypeV>(val_slot1->_ptr);
+ TypeK* ptr1 = (TypeV*) val_slot1->_ptr;
if (val_slot2 == NULL || ptr1 == NULL) return false;
return ptr1->equals(val_slot2->_ptr);
}
}
// A wrapper of the essential function putIfMatch()
- shared_ptr<TypeV> putIfMatch(TypeK& key, TypeV& value, slot *old_val) {
+ TypeV* putIfMatch(TypeK& key, TypeV& value, slot *old_val) {
// TODO: Should throw an exception rather return NULL
if (old_val == NULL) {
return NULL;
}
void *key_ptr = (void*) new TypeK(key);
- slot *key_slot = new slot(false, shared_ptr<void>(key_ptr));
+ slot *key_slot = new slot(false, key_ptr);
void *val_ptr = (void*) new TypeV(value);
- slot *value_slot = new slot(false, shared_ptr<void>(val_ptr));
- slot *res = putIfMatch(this, _kvs, key_slot, value_slot, old_val);
+ slot *value_slot = new slot(false, val_ptr);
+ kvs_data *kvs = _kvs.load(memory_order_acquire);
+ slot *res = putIfMatch(this, kvs, key_slot, value_slot, old_val);
// Only when copy_slot() call putIfMatch() will it return NULL
assert (res != NULL);
assert (!is_prime(res));
- return res == TOMBSTONE ? NULL : static_pointer_cast<TypeV>(res->_ptr);
+ return res == TOMBSTONE ? NULL : (TypeV*) res->_ptr;
}
/**