leveldb skiplist的改编非并发去除内存池版本 代码练习
// MuSkipList.cpp: 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <random>
#include <iostream>
#include <set>
#include <assert.h> using namespace std; typedef unsigned _int64 Key; struct Comparator {
int operator()(const Key& a, const Key& b) const {
if (a < b) {
return -;
}
else if (a > b) {
return +;
}
else {
return ;
}
}
}; unsigned GetRand()
{
static std::default_random_engine e;
static std::uniform_int_distribution<unsigned> u(, );
return u(e);
}
//=================================================================== template<typename Key, class Comparator>
class SkipList {
private:
struct Node;
public:
explicit SkipList(Comparator cmp);
void Insert(const Key& key);
bool Contains(const Key& key) const; class Iterator {
public:
explicit Iterator(const SkipList* list);
bool Valid() const;
const Key& key() const;
void Next();
void Prev();
void Seek(const Key& target);
void SeekToFirst();
void SeekToLast();
private:
const SkipList* list_;
Node* node_;
};
private:
enum { kMaxHeight = };
Comparator const compare_;
Node* head_;
int max_height_;
inline int GetMaxHeight() const {
return max_height_;
}
//Random rnd_; Node* NewNode(const Key& key, int height);
int RandomHeight();
bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == ); }
bool KeyIsAfterNode(const Key& key, Node* n) const;
Node* FindGreaterOrEqual(const Key& key, Node** prev)const;
Node* FindLessThan(const Key& key) const;
SkipList(const SkipList&);
Node* FindLast() const;
void operator=(const SkipList&);
}; template<typename Key, class Comparator>
struct SkipList<Key, Comparator>::Node {
explicit Node(const Key& k) : key(k) { }
Key const key;
Node* Next(int n) {
assert(n >= );
return (next_[n]);
}
void SetNext(int n, Node* x) {
assert(n >= );
next_[n] = (x);
}
Node* NoBarrier_Next(int n) {
assert(n >= );
return next_[n];
}
void NoBarrier_SetNext(int n,Node* x) {
assert(n >= );
next_[n] = (x);
} private:
Node* next_[];
}; template<typename Key, class Comparator>
typename SkipList<Key, Comparator>::Node*
SkipList<Key, Comparator>::NewNode(const Key& key, int height) {
char* mem = new char[sizeof(Node) + sizeof(Node*) * (height - )];
return ::new (mem) Node(key);
} template<typename Key, class Comparator>
inline SkipList<Key, Comparator>::Iterator::Iterator(const SkipList* list) {
list_ = list;
node_ = NULL;
} template<typename Key, class Comparator>
inline bool SkipList<Key, Comparator>::Iterator::Valid() const {
return node_ != NULL;
} template<typename Key, class Comparator>
inline const Key& SkipList<Key, Comparator>::Iterator::key() const {
assert(Valid());
return node_->key;
} template<typename Key, class Comparator>
inline void SkipList<Key, Comparator>::Iterator::Next() {
assert(Valid());
node_ = node_->Next();
} template<typename Key, class Comparator>
inline void SkipList<Key, Comparator>::Iterator::Prev() {
// Instead of using explicit "prev" links, we just search for the
// last node that falls before key.
assert(Valid());
node_ = list_->FindLessThan(node_->key);
if (node_ == list_->head_) {
node_ = NULL;
}
} template<typename Key, class Comparator>
inline void SkipList<Key, Comparator>::Iterator::Seek(const Key& target) {
node_ = list_->FindGreaterOrEqual(target, NULL);
} template<typename Key, class Comparator>
inline void SkipList<Key, Comparator>::Iterator::SeekToFirst() {
node_ = list_->head_->Next();
} template<typename Key, class Comparator>
inline void SkipList<Key, Comparator>::Iterator::SeekToLast() {
node_ = list_->FindLast();
if (node_ == list_->head_) {
node_ = NULL;
}
} template<typename Key, class Comparator>
int SkipList<Key, Comparator>::RandomHeight() {
// Increase height with probability 1 in kBranching
static const unsigned int kBranching = ;
int height = ;
while (height < kMaxHeight && ((GetRand() % kBranching) == )) {
height++;
}
assert(height > );
assert(height <= kMaxHeight);
return height;
} template<typename Key, class Comparator>
bool SkipList<Key, Comparator>::KeyIsAfterNode(const Key& key, Node* n) const {
// NULL n is considered infinite
return (n != NULL) && (compare_(n->key, key) < );
} template<typename Key, class Comparator>
typename SkipList<Key, Comparator>::Node* SkipList<Key, Comparator>::FindGreaterOrEqual(const Key& key, Node** prev )const
{
Node* x = head_;
int level = GetMaxHeight() - ;
while (true) {
Node* next = x->Next(level);
if (KeyIsAfterNode(key, next)) {
// Keep searching in this list
x = next;
}
else {
if (prev != NULL) prev[level] = x;
if (level == ) {
return next;
}
else {
// Switch to next list
level--;
}
}
}
} template<typename Key, class Comparator>
typename SkipList<Key, Comparator>::Node*
SkipList<Key, Comparator>::FindLessThan(const Key& key) const {
Node* x = head_;
int level = GetMaxHeight() - ;
while (true) {
assert(x == head_ || compare_(x->key, key) < );
Node* next = x->Next(level);
if (next == NULL || compare_(next->key, key) >= ) {
if (level == ) {
return x;
}
else {
// Switch to next list
level--;
}
}
else {
x = next;
}
}
} template<typename Key, class Comparator>
typename SkipList<Key, Comparator>::Node* SkipList<Key, Comparator>::FindLast()
const {
Node* x = head_;
int level = GetMaxHeight() - ;
while (true) {
Node* next = x->Next(level);
if (next == NULL) {
if (level == ) {
return x;
}
else {
// Switch to next list
level--;
}
}
else {
x = next;
}
}
} template<typename Key, class Comparator>
SkipList<Key, Comparator>::SkipList(Comparator cmp)
: compare_(cmp),
head_(NewNode( /* any key will do */, kMaxHeight)),
max_height_(())
{
for (int i = ; i < kMaxHeight; i++) {
head_->SetNext(i, NULL);
}
} template<typename Key, class Comparator>
void SkipList<Key, Comparator>::Insert(const Key& key) {
Node* prev[kMaxHeight];
Node* x = FindGreaterOrEqual(key, prev); assert(x == NULL || !Equal(key, x->key)); int height = RandomHeight();
if (height > GetMaxHeight()) {
for (int i = GetMaxHeight(); i < height; i++) {
prev[i] = head_;
} max_height_=(height);
} x = NewNode(key, height);
for (int i = ; i < height; i++) {
x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i));
prev[i]->SetNext(i, x);
}
} template<typename Key, class Comparator>
bool SkipList<Key, Comparator>::Contains(const Key& key) const {
Node* x = FindGreaterOrEqual(key, NULL);
if (x != NULL && Equal(key, x->key)) {
return true;
}
else {
return false;
}
} //=======================================================================
int main()
{
{
Comparator cmp;
SkipList<Key, Comparator> list(cmp); assert(false ==list.Contains());
SkipList<Key, Comparator>::Iterator iter(&list); assert(!iter.Valid());
iter.SeekToFirst();
assert(!iter.Valid());
iter.Seek();
assert(!iter.Valid());
iter.SeekToLast();
assert(!iter.Valid());
} const int N = ;
const int R = ;
std::set<Key> keys;
Comparator cmp;
SkipList<Key, Comparator> list(cmp);
{ for (int i = ; i < N; i++) {
Key key = GetRand() % R;
if (keys.insert(key).second) {
list.Insert(key);
}
} for (int i = ; i < R; i++) {
if (list.Contains(i)) {
assert(keys.count(i)== );
}
else {
assert(keys.count(i)== );
}
} } // Simple iterator tests
{
SkipList<Key, Comparator>::Iterator iter(&list);
assert(!iter.Valid()); iter.Seek();
assert(iter.Valid());
assert(*(keys.begin()) == iter.key()); iter.SeekToFirst();
assert(iter.Valid());
assert(*(keys.begin()) == iter.key()); iter.SeekToLast();
assert(iter.Valid());
assert(*(keys.rbegin())== iter.key());
} // Forward iteration test
for (int i = ; i < R; i++) {
SkipList<Key, Comparator>::Iterator iter(&list);
iter.Seek(i); // Compare against model iterator
std::set<Key>::iterator model_iter = keys.lower_bound(i);
for (int j = ; j < ; j++) {
if (model_iter == keys.end()) {
assert(!iter.Valid());
break;
}
else {
assert(iter.Valid());
assert(*model_iter == iter.key());
++model_iter;
iter.Next();
}
}
} // Backward iteration test
{
SkipList<Key, Comparator>::Iterator iter(&list);
iter.SeekToLast(); // Compare against model iterator
for (std::set<Key>::reverse_iterator model_iter = keys.rbegin();
model_iter != keys.rend();
++model_iter) {
assert(iter.Valid());
assert(*model_iter == iter.key());
iter.Prev();
}
assert(!iter.Valid());
} return ;
}
把LEVELDB的skiplist跳表给扣出来了 去除了内存池代码
贪图方便 还是选择了原始指针.
需要在析构函数中遍历节点 进行Node的指针的 delete
如果想使用智能指针替代 动态分配Node的指针的时候 可以考虑使用 std::array<std::shared_ptr<Node>> 或者 std::vector<std::shared_ptr<Node>>
在leveldb项目中 原代码文件路径为
leveldb-windows\db\skiplist.h
leveldb-windows\db\skiplist_test.cc
leveldb skiplist的改编非并发去除内存池版本 代码练习的更多相关文章
- C++实现简单的内存池
多进程编程多用在并发服务器的编写上,当收到一个请求时,服务器新建一个进程处理请求,同时继续监听.为了提高响应速度,服务器采用进程池的方法,在初始化阶段创建一个进程池,池中有许多预创建的进程,当请求到达 ...
- Linux设备驱动程序 之 内存池
内核中有些地方的内存分配是不允许失败的,为了确保这种情况下的成功分配,内核开发者建立了一种称为内存池的抽象:内存池其实就是某种形式的后备高速缓存,它试图始终保存空闲的内存,以便在紧急状态下使用: me ...
- linux内存池
在内核中有不少地方内存分配不允许失败. 作为一个在这些情况下确保分配的方式, 内核 开发者创建了一个已知为内存池(或者是 "mempool" )的抽象. 一个内存池真实地只是一 类 ...
- Linux 内核内存池
内核中经常进行内存的分配和释放.为了便于数据的频繁分配和回收,通常建立一个空闲链表——内存池.当不使用的已分配的内存时,将其放入内存池中,而不是直接释放掉. Linux内核提供了slab层来管理内存的 ...
- LevelDB学习笔记 (3): 长文解析memtable、跳表和内存池Arena
LevelDB学习笔记 (3): 长文解析memtable.跳表和内存池Arena 1. MemTable的基本信息 我们前面说过leveldb的所有数据都会先写入memtable中,在leveldb ...
- Golang面向并发的内存模型
Import Advanced Go Programming 1.5 面向并发的内存模型 在早期,CPU都是以单核的形式顺序执行机器指令.Go语言的祖先C语言正是这种顺序编程语言的代表.顺序编程语言中 ...
- NSOperation的start与main,并发与非并发。
http://blog.csdn.net/a2331046/article/details/52294006 在ios4以前,只有非并发的情况下,队列会为operation开启一个线程来执行.如果是并 ...
- LevelDB源码分析之:arena内存管理
一.原理 arena是LevelDB内部实现的内存池. 我们知道,对于一个高性能的服务器端程序来说,内存的使用非常重要.C++提供了new/delete来管理内存的申请和释放,但是对于小对象来说,直接 ...
- NSOperation的并发与非并发
NSoperation也是多线程的一种,NSopertaion有2种形式 (1) 并发执行 并发执行你需要重载如下4个方法 //执行任务主函数,线程运行的入口函数 - (v ...
随机推荐
- linux centos 基本命令
init 3 进入命令行界面. init 5 进入图形界面. ifconfig 查询IP地址. nmtui 设置网卡. su - root 是切换到root账号使用,使用的是root用户的环境变量:s ...
- 1.3、CDH 搭建Hadoop在安装之前(端口)
端口 Cloudera Manager,CDH组件,托管服务和第三方组件使用下表中列出的端口.在部署Cloudera Manager,CDH和托管服务以及第三方组件之前,请确保在每个系统上打开这些端口 ...
- Functional and Class Components
[Functional and Class Components] The simplest way to define a component is to write a JavaScript fu ...
- android 区分wifi是5G还是2.4G(转)
http://bbs.csdn.net/topics/391033966?page=1 我一开始看这帖子,找不到答案,为了后来的人,我来回复吧.WifiManager wifiManager = (W ...
- spring boot 启动错误:Could not resolve placeholder
在启动整个spring boot项目时,出现错误: Could not resolve placeholder 原因:没有指定好配置文件,因为src/main/resources下有多个配置文件,例如 ...
- C library:<cctype>(ctype.h)
1, isalnum(): check whether c is either a decimal digit or an uppercase or lowercase letter. 2, isal ...
- kafka集群压力测试--基础。
1.生产者测试 kafka-producer-perf-test.bat --num-records 1000000 --topic test --record-size 200 --throughp ...
- awk技巧 nginx access.log
1.1 介绍 awk其名称得自于它的创始人 Alfred Aho .Peter Weinberger 和 Brian Kernighan 姓氏的首个字母.实际上 AWK 的确拥有自己的语言: AWK ...
- ASP.Net MVC 在ajax接收controller返回值为Json数据
首先,再次回忆一下ajax的标准用法:(这张图写的比较详细了)(转) 页面部分ajax代码: $.ajax({ url: "/Home/Login?account=&q ...
- TableView中Label自适应高度
//Xcode6.3以后label自适应需要添加两个属性 _tableView.rowHeight = UITableViewAutomaticDimension; //给予预计行高 _tableVi ...