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 ...
随机推荐
- Web前端js下载流文件
前端下载文件大概有以下种: 1)a标签链接下载 <a href="url">点击链接下载</a> 2)表单form提交下载 var form = $(&qu ...
- MS17-010漏洞检测
1.扫描脚本的下载和加载 由于Metasploit还没有更新MS17-010检测的模块,所以要去exploit-db下载,并在MSF中加载. cd /usr/share/metasploit-fram ...
- JS的6种常见继承模式
数天前在知乎看到有人阿里面试被问到这个问题,我来总结一下. 1. 原型链继承: function SuperType() { this.property = true; } SuperType.pro ...
- UltraEdit窗口布局重新设置
解决办法:工具栏中的视图-->环境-->左边小框里选择“编程员”,再点选择环境 转载:https://blog.csdn.net/u011650048/article/details/18 ...
- phacon只能访问index action
location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?_url=$1 last; break; } }
- 二:python 对象类型概述
1,为什么使用内置类型: a)内置对象使程序更容易编写 b)内置对象是扩展的组件 c)内置对象往往比定制的数据结构更加高效 d)内置对象是语言的标准的一部分 2,python 的主要内置对象 对象类 ...
- oracle 修改数据精度问题
今天,在建表后插入语句时,报了这样的错误,对于这样的错误,搜集了一些资料,进行了总结如下: 建表语句: 1 2 3 4 5 6 7 8 9 create table pre_info( pre_cod ...
- windows上安装Anaconda和python
下载并安装 anaconda 先到https://www.continuum.io/downloads 下载anaconda, 现在的版本有python2.7版本和python3.5版本,下载好对应版 ...
- Mysql数据备份与还原
一.数据备份 1.使用mysqldump命令备份 mysqldump命令将数据库中的数据备份成一个文本文件.表的结构和表中的数据将存储在生成的文本文件中. mysqldump命令的工作原理很简单.它先 ...
- 基于RBAC权限验证, 中间价middleware实现, views 登录视图代码
废话不多说 上代码: 基础实现: rom django.shortcuts import HttpResponse, redirect, render from django.http import ...