Skip to content
Snippets Groups Projects
Commit fc59542e authored by Recolic Keghart's avatar Recolic Keghart
Browse files

before using lock-free version!

parent a260d4af
No related branches found
No related tags found
No related merge requests found
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Make it larger if you have more nodes! # Make it larger if you have more nodes!
# If SIZEHINT is smaller, the program is always quicker, and always consumes more RAM. # If SIZEHINT is smaller, the program is always quicker, and always consumes more RAM.
SIZEHINT ?= 3.0 # Single process SIZEHINT ?= 3.0 # Single process
CXX = upcxx -O3 -std=c++14 -DHASHMAP_SIZE_HINT_FACTOR=$(SIZEHINT) CXX = upcxx -O3 -std=c++14 -DHASHMAP_SIZE_HINT_FACTOR=$(SIZEHINT) -g
# upcxx-meta PPFLAGS are really CFLAGS to be used during compilation # upcxx-meta PPFLAGS are really CFLAGS to be used during compilation
# upcxx-meta LDFLAGS are really CFLAGS to be used during linking # upcxx-meta LDFLAGS are really CFLAGS to be used during linking
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <stdexcept> #include <stdexcept>
#include <mutex> #include <mutex>
#include "rlib.stdio.min.hpp" #include "rlib.stdio.min.hpp"
#include "rlib_concurrent_list.hpp"
#ifndef R267_KVS_DEF_SLOT_PER_NODE #ifndef R267_KVS_DEF_SLOT_PER_NODE
#define R267_KVS_DEF_SLOT_PER_NODE 1024 #define R267_KVS_DEF_SLOT_PER_NODE 1024
...@@ -32,7 +33,8 @@ public: ...@@ -32,7 +33,8 @@ public:
// kv_type should be default_constructable. // kv_type should be default_constructable.
private: private:
using slot_type = std::list<std::pair<key_type, value_type>>; //using slot_type = std::list<std::pair<key_type, value_type>>;
using slot_type = rlib::concurrency::single_list<std::pair<key_type, value_type>>;
public: public:
kv_store(size_t my_rank, size_t n_rank, size_t slot_per_node = R267_KVS_DEF_SLOT_PER_NODE) kv_store(size_t my_rank, size_t n_rank, size_t slot_per_node = R267_KVS_DEF_SLOT_PER_NODE)
...@@ -107,7 +109,8 @@ private: ...@@ -107,7 +109,8 @@ private:
} }
} }
// duplicate element not found. Insert it. // duplicate element not found. Insert it.
target_ls.push_front(std::make_pair(k, v)); // target_ls.push_front(std::make_pair(k, v));
target_ls.push_back(std::make_pair(k, v));
} }
} }
......
#ifndef RLIB_CONCURR_LIST_HPP_
#define RLIB_CONCURR_LIST_HPP_
#include <atomic>
#include <iterator>
namespace rlib {
namespace concurrency {
template <typename T>
class single_list {
struct node {
T data;
std::atomic<node *> next;
node(T &&data, node *next = nullptr) : data(data), next(next) {}
};
public:
using element_type = T;
using this_type = single_list<T>;
single_list() : possible_tail(nullptr), root(nullptr) {}
void push_back(T &&ele) {
node *new_node = new node(std::forward<T>(ele));
node *null_ = nullptr;
// DO NOT allow pop_back.
if(possible_tail == nullptr) {
if(std::atomic_compare_exchange_strong(&possible_tail, &null_, new_node)) {
root = new_node;
return;
}
}
while(!std::atomic_compare_exchange_weak(&(possible_tail.load()->next), &null_, new_node));
possible_tail.store(new_node);
}
public:
class iterator : std::forward_iterator_tag {
friend class single_list<T>;
public:
using pointer = T *;
using reference = T &;
using this_type = iterator;
explicit iterator(node * ptr) : ptr(ptr) {}
reference operator*() const {
// If this is an iterator to empty_list.begin(), then nullptr->data throws.
return ptr->data;
}
pointer operator->() const {
// If this is an iterator to empty_list.begin(), then nullptr->data throws.
return &ptr->data;
}
this_type &operator++() {
ptr = ptr->next;
return *this;
}
const this_type operator++(int) {
iterator backup(ptr);
operator++();
return std::move(backup);
}
bool operator==(const this_type &another) const {
return ptr == another.ptr;
}
bool operator!=(const this_type &another) const {
return !operator==(another);
}
private:
node * ptr;
};
class const_iterator : std::forward_iterator_tag {
friend class single_list<T>;
public:
using pointer = const T *;
using reference = const T &;
using this_type = const_iterator;
explicit const_iterator(const node * ptr) : ptr(ptr) {}
reference operator*() const {
// If this is an iterator to empty_list.begin(), then nullptr->data throws.
return ptr->data;
}
pointer operator->() const {
// If this is an iterator to empty_list.begin(), then nullptr->data throws.
return &ptr->data;
}
this_type &operator++() {
ptr = ptr->next;
return *this;
}
const this_type operator++(int) {
iterator backup(ptr);
operator++();
return std::move(backup);
}
bool operator==(const this_type &another) const {
return ptr == another.ptr;
}
bool operator!=(const this_type &another) const {
return !operator==(another);
}
private:
const node * ptr;
};
iterator begin() {
return iterator(root);
}
iterator end() {
return iterator(nullptr);
}
const_iterator begin() const {
return const_iterator(root);
}
const_iterator end() const {
return const_iterator(nullptr);
}
const_iterator cbegin() const {
return const_iterator(root);
}
const_iterator cend() const {
return const_iterator(nullptr);
}
private:
node * root;
volatile std::atomic<node *> possible_tail;
};
}
}
#endif
\ No newline at end of file
#include "rlib_concurrent_list.hpp"
#include "rlib.stdio.min.hpp"
int main() {
rlib::concurrency::single_list<int> l;
l.push_back(123);
l.push_back(666);
l.push_back(666);
l.push_back(666);
l.push_back(666);
l.push_back(6166);
l.push_back(666);
l.push_back(666);
for(auto &&ele : l) {
rlib::println(ele);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment