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

#ifndef _SKIPLIST_H
#define _SKIPLIST_H

#include <iostream>
#include<atomic>

#define DEBUG 1

namespace 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 DEBUG
	struct _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();
#endif
private:
	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 DEBUG
template<typename Key>
void SkipList<Key>::inListCount()
{
	for (auto itr = begin().next(0); itr != end(); itr = itr.next(0))
	{
		++debug_counter.in_list_counter;
	}	
}
#endif

template<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 DEBUG
	debug_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 DEBUG
	skiplist.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;
#endif

	return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值