线程安全的skiplist,lockfree,CAS,c11版

来源:互联网 发布:美国gdp数据公布时间 编辑:程序博客网 时间:2024/05/16 14:17
#ifndef _SKIPLIST_H#define _SKIPLIST_H#include <iostream>#include<atomic>#define DEBUG 1namespace microdb{template<typename Key>class SkipList{public:static const unsigned int MAXLEVEL = 4;class Node{public:explicit Node(const Key& key);bool setNext(Node* expected, Node* node, unsigned int level);void setNextWithoutAtomic(Node* node, unsigned int level);Node* getNext(unsigned int level);const Key& key() const;private:Key key_;std::atomic<Node*> next_[MAXLEVEL];};class Iterator{public:Iterator();explicit Iterator(Node* node);Iterator next(unsigned int level);Node* operator->();Node& operator*();bool operator==(Iterator& itr) const;bool operator!=(Iterator& itr) const;const Key& key() const;Node* node() const;private:Node* node_;};explicit SkipList(const Key& key);void put(const Key& key);bool get(const Key& key);void remove(const Key& key);void print();Iterator& begin();Iterator& end();#if DEBUGstruct _debug_counter{std::atomic<unsigned int> inserted_counter;std::atomic<unsigned int> not_inserted_counter;std::atomic<unsigned int> in_list_counter;}debug_counter;void inListCount();#endifprivate:int random(); SkipList<Key>::Iterator lowerBound(const Key& key, unsigned int level);SkipList<Key>::Iterator upperBound(const Key& key, unsigned int level);Node* head_;Iterator begin_;Iterator end_;};template<typename Key>SkipList<Key>::Node::Node(const Key& key){key_ = key;for (auto i = 0; i < MAXLEVEL; ++i){next_[i] = nullptr;}}template<typename Key>bool SkipList<Key>::Node::setNext(Node* expected, Node* node, unsigned int level){return next_[level].compare_exchange_strong(expected, node, std::memory_order_seq_cst, std::memory_order_seq_cst);//while (true)//{//if (next_[level].compare_exchange_strong(expected, node, std::memory_order_seq_cst, std::memory_order_seq_cst))//{//return;//}//else//{//std::cout<<"Update failed!"<<std::endl;//}//}}template<typename Key>void SkipList<Key>::Node::setNextWithoutAtomic(Node* node, unsigned int level){        next_[level].store(node);}template<typename Key>typename SkipList<Key>::Node* SkipList<Key>::Node::getNext(unsigned int level){return next_[level].load(std::memory_order_seq_cst);}template<typename Key>const Key& SkipList<Key>::Node::key() const{return key_;}template<typename Key>SkipList<Key>::Iterator::Iterator(Node* node){node_ = node; }template<typename Key>SkipList<Key>::Iterator::Iterator(){        node_ = nullptr;}template<typename Key>typename SkipList<Key>::Iterator SkipList<Key>::Iterator::next(unsigned int level){Iterator tmp(node_);if (tmp.node_){tmp.node_ = tmp.node_->getNext(level);}return tmp;}template<typename Key>typename SkipList<Key>::Node* SkipList<Key>::Iterator::operator->(){return node_;}template<typename Key>typename SkipList<Key>::Node& SkipList<Key>::Iterator::operator*(){return *node_;}template<typename Key>bool SkipList<Key>::Iterator::operator==(Iterator& itr) const{return (node_ == itr.node_);}template<typename Key>bool SkipList<Key>::Iterator::operator!=(Iterator& itr) const{return (node_ != itr.node_);}template<typename Key>const Key& SkipList<Key>::Iterator::key() const{return node_->key();}template<typename Key>typename SkipList<Key>::Node* SkipList<Key>::Iterator::node() const{return node_;}template<typename Key>typename SkipList<Key>::Iterator& SkipList<Key>::begin(){return begin_;}template<typename Key>typename SkipList<Key>::Iterator& SkipList<Key>::end(){return end_;}#if DEBUGtemplate<typename Key>void SkipList<Key>::inListCount(){for (auto itr = begin().next(0); itr != end(); itr = itr.next(0)){++debug_counter.in_list_counter;}}#endiftemplate<typename Key>int SkipList<Key>::random(){return rand() % MAXLEVEL;}template<typename Key>SkipList<Key>::SkipList(const Key& key){head_ = new Node(key);begin_ = Iterator(head_);end_ = Iterator(nullptr);#if DEBUGdebug_counter.inserted_counter = 0;debug_counter.not_inserted_counter = 0;debug_counter.in_list_counter = 0;#endif}template<typename Key>typename SkipList<Key>::Iterator SkipList<Key>::lowerBound(const Key& key, unsigned int level){auto itr = begin();for (itr = begin().next(level); itr != end() && key > itr->key(); itr = itr.next(level)){}return itr;}template<typename Key>typename SkipList<Key>::Iterator SkipList<Key>::upperBound(const Key& key, unsigned int level){auto last_itr = begin();        for (auto itr = begin().next(level); itr != end() && key > itr->key(); itr = itr.next(level))        {last_itr = itr;        }return last_itr;}template<typename Key>void SkipList<Key>::put(const Key& key){int level = random();SkipList<Key>::Iterator pre;SkipList<Key>::Iterator next;Node* new_node = new Node(key);for (auto i = level; i >= 0; --i){while (true){pre = upperBound(key, i);next = pre.next(i);if (next != end()){if (next->key() == key){#if DEBUG++debug_counter.not_inserted_counter;#endif//std::cout<<"The key has existed! "<<key<<" Just return"<<std::endl;delete new_node;return;}}new_node->setNextWithoutAtomic(next.node(), i);auto tmp = next.node();if (pre->setNext(tmp, new_node, i)){break;}}}#if DEBUG++debug_counter.inserted_counter;#endif}template<typename Key>void SkipList<Key>::print(){std::cout<<"################## Print my Skiplist ##################"<<std::endl;for (auto i = 0; i < MAXLEVEL; ++i){std::cout<<"Level "<<i<<" :"<<std::endl;for (auto itr = begin().next(i); itr != end(); itr = itr.next(i)){std::cout<<itr->key()<<" ";}std::cout<<std::endl;}std::cout<<"########## Print my Skiplist, it is the end ##########"<<std::endl;}} // namespace microdb#endif // _SKIPLIST_H


#include "skiplist.h"#include <sys/time.h>#include <thread>int main(){microdb::SkipList<int> skiplist(0);std::thread threads[10000];timeval start, end;gettimeofday(&start, NULL); for (auto i = 0; i < 10000; ++i)        {                threads[i] = std::thread(std::mem_fn(µdb::SkipList<int>::put), &skiplist, i);        }        for (auto i = 0; i < 10000; ++i)        {                threads[i].join();        }        gettimeofday(&end, NULL);        unsigned long time = 1000000L * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);        std::cout<<"Total insert time "<<time<<std::endl;#if DEBUGskiplist.inListCount();std::cout<<"Inserted "<<skiplist.debug_counter.inserted_counter<<" and not inserted "<<skiplist.debug_counter.not_inserted_counter<<" and total "<<skiplist.debug_counter.inserted_counter + skiplist.debug_counter.not_inserted_counter<<" and in list "<<skiplist.debug_counter.in_list_counter<<std::endl;#endifreturn 0;}


原创粉丝点击