1.概述
书接上回上上回定时器实现之最小堆(一)与定时器实现之红黑树(二),本文是使用跳表实现定时器,跳表有序的特性不必多说,感兴趣的可自行研究。
2.代码实现
文字无力直接肝代码吧。
//zkiplist.h
#pragma once
#define ZSKIPLIST_MAXLEVEL 32 /* Should be enough for 2^64 elements */
#define ZSKIPLIST_P 0.25 /* Skiplist P = 1/2 */
struct zskiplistNode;
struct zskiplistLevel {
zskiplistNode *forward;
};
struct zskiplistNode {
unsigned long long score; // 时间戳
zskiplistLevel* level;
};
typedef struct zskiplist {
struct zskiplistNode *header;
int length;
int level;
} zskiplist;
zskiplist* zslCreate();
void zslFree(zskiplist* zsl);
bool zslInsert(zskiplist* zsl, zskiplistNode* node);
zskiplistNode* zslMin(zskiplist *zsl);
void zslDeleteHead(zskiplist* zsl);
void zslDelete(zskiplist* zsl, zskiplistNode* zn);
int zslRandomLevel(void);
zskiplistNode* zslCreateNode(int level, unsigned long score);
void zslDeleteNode(zskiplistNode* node);
void* zslCreateLevel(int level);
//zkiplist.cpp
#include "zkiplist.h"
#include <cstdlib>
int zslRandomLevel(void) {
int level = 1;
while ((rand()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
level += 1;
return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}
static void zslDeleteNode(zskiplist *zsl, zskiplistNode *x, zskiplistNode **update) {
int i;
for (i = 0; i < zsl->level; i++) {
if (update[i]->level[i].forward == x) {
update[i]->level[i].forward = x->level[i].forward;
}
}
while(zsl->level > 1 && zsl->header->level[zsl->level-1].forward == NULL)
zsl->level--;
zsl->length--;
}
zskiplistNode *zslCreateNode(int level, unsigned long score) {
zskiplistNode* zn = (zskiplistNode*)malloc(sizeof(zskiplistNode) + level * sizeof(zskiplistLevel));
zn->level = (zskiplistLevel*)malloc(level * sizeof(zskiplistLevel));
zn->score = score;
return zn;
}
zskiplist *zslCreate(void) {
int j = 0;
zskiplist* zsl = nullptr;
zsl = (zskiplist*)malloc(sizeof(zskiplist));
zsl->level = 1;
zsl->length = 0;
zsl->header = zslCreateNode(ZSKIPLIST_MAXLEVEL,0);
for (j = 0; j < ZSKIPLIST_MAXLEVEL; j++) {
zsl->header->level[j].forward = NULL;
}
return zsl;
}
void zslFree(zskiplist *zsl) {
zskiplistNode *node = zsl->header->level[0].forward, *next;
free(zsl->header->level);
free(zsl->header);
while(node) {
next = node->level[0].forward;
free(node);
node = next;
}
free(zsl);
}
bool zslInsert(zskiplist *zsl, zskiplistNode* node) {
zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
int i, level;
x = zsl->header;
for (i = zsl->level-1; i >= 0; i--) {
while (x->level[i].forward &&
x->level[i].forward->score < node->score)
{
x = x->level[i].forward;
}
update[i] = x;
}
level = zslRandomLevel();
if (level > zsl->level) {
for (i = zsl->level; i < level; i++) {
update[i] = zsl->header;
}
zsl->level = level;
}
x = node;
for (i = 0; i < level; i++) {
x->level[i].forward = update[i]->level[i].forward;
update[i]->level[i].forward = node;
}
zsl->length++;
return true;
}
zskiplistNode* zslMin(zskiplist *zsl) {
zskiplistNode *x;
x = zsl->header;
return x->level[0].forward;
}
void zslDeleteHead(zskiplist* zsl) {
zskiplistNode *update[ZSKIPLIST_MAXLEVEL];
zskiplistNode *x = zslMin(zsl);
if (!x) return;
int i;
for (i = zsl->level-1; i >= 0; i--) {
if (zsl->header->level[i].forward == x) {
zsl->header->level[i].forward = x->level[i].forward;
}
}
while(zsl->level > 1 && zsl->header->level[zsl->level-1].forward == NULL)
zsl->level--;
zsl->length--;
}
void zslDelete(zskiplist* zsl, zskiplistNode* zn) {
zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
int i;
x = zsl->header;
for (i = zsl->level-1; i >= 0; i--) {
while (x->level[i].forward &&
x->level[i].forward->score < zn->score)
{
x = x->level[i].forward;
}
update[i] = x;
}
x = x->level[0].forward;
if (x && zn->score == x->score) {
zslDeleteNode(zsl, x, update);
}
}
void zslDeleteNode(zskiplistNode* node) {
if(node) {
free(node->level);
}
}
void* zslCreateLevel(int level) {
return malloc(level * sizeof(zskiplistLevel));
}
//main.cpp
#include "minheap.h"
#include "rbtree.h"
#include "zkiplist.h"
#include <cstdint>
#include <iostream>
#include <functional>
#include <chrono>
#include <ctime>
#include <thread>
enum TimeType {
MIN_HEAP,
RBTREE,
ZKIPLIST,
};
extern "C"{
#define offsetofs(s,m) (size_t)(&reinterpret_cast<const volatile char&>((((s*)0)->m)))
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetofs(type, member) );})
}
using CallBack = std::function<void(void)>;
struct TimeNode {
timer_entry env;
CallBack cb;
};
struct TimeNodeRb {
rbtree_node env;
CallBack cb;
};
struct TimeNodeZp {
zskiplistNode env;
CallBack cb;
};
class Timer {
public:
Timer(uint32_t size);
Timer(uint32_t size, TimeType Type);
Timer() = delete;
~Timer();
int addTimer(uint64_t time, CallBack cb);
void run();
void stop();
private:
uint64_t GetNowTime();
void AddMinHeapTimer(uint64_t time, CallBack cb);
void AddRbtreeTimer(uint64_t time, CallBack cb);
void AddZskiplistTimer(uint64_t time, CallBack cb);
private:
min_heap* _heap;
rbtree* _rbtree;
bool _close;
TimeType _Type;
zskiplist* _zskiplist;
};
Timer::Timer(uint32_t size) {
min_heap_init(&_heap, size);
_close = false;
}
Timer::Timer(uint32_t size, TimeType Type) {
switch (Type) {
case MIN_HEAP:
min_heap_init(&_heap, size);
break;
case RBTREE:
_rbtree = new rbtree();
if(_rbtree) {
_rbtree->sentinel = new rbtree_node();
rbtree_init(_rbtree, _rbtree->sentinel);
}
break;
case ZKIPLIST:
_zskiplist = zslCreate();
}
_close = false;
_Type = Type;
}
Timer::~Timer() {
switch (_Type) {
case MIN_HEAP:
min_heap_free(_heap);
break;
case RBTREE:
delete _rbtree->sentinel;
delete _rbtree;
break;
case ZKIPLIST:
zslFree(_zskiplist);
break;
}
}
int Timer::addTimer(uint64_t time, CallBack cb) {
switch (_Type) {
case MIN_HEAP:
AddMinHeapTimer(time, cb);
break;
case RBTREE:
AddRbtreeTimer(time, cb);
break;
case ZKIPLIST:
AddZskiplistTimer(time, cb);
break;
}
return 0;
}
uint64_t Timer::GetNowTime() {
auto now = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
uint64_t timestamp_ms = duration.count();
return timestamp_ms;
}
void Timer::run() {
while(!_close) {
uint64_t sleep = 50;
uint64_t now = GetNowTime();
switch (_Type) {
case MIN_HEAP: {
timer_entry *entry = nullptr;
if (!min_heap_top(_heap, &entry)) {
if (entry->time <= now) {
if (!min_heap_pop(_heap, &entry)) {
TimeNode *node = container_of(entry, TimeNode, env);
if (node) {
node->cb();
}
delete node;
}
} else {
sleep = entry->time - now;
}
}
}
case RBTREE: {
rbtree_node* node = rbtree_min(_rbtree);
if(!node) {
break;
}
if(node->key <= now) {
rbtree_delete(_rbtree, node);
TimeNodeRb* n = container_of(node, TimeNodeRb, env);
n->cb();
delete n;
} else {
sleep = node->key - now;
}
}
case ZKIPLIST: {
zskiplistNode* node = zslMin(_zskiplist);
if(!node) {
break;
}
if(node->score <= now) {
zslDeleteHead(_zskiplist);
TimeNodeZp* n = container_of(node, TimeNodeZp, env);
if(n) {
n->cb();
zslDeleteNode(&n->env);
delete n;
}
}else {
sleep = node->score - now;
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
}
}
void Timer::stop() {
_close = true;
}
void Timer::AddMinHeapTimer(uint64_t time, CallBack cb) {
TimeNode* node = new TimeNode();
node->env.time = GetNowTime() + time;
node->cb = cb;
min_heap_push(_heap, &node->env);
}
void Timer::AddRbtreeTimer(uint64_t time, CallBack cb) {
TimeNodeRb* node = new TimeNodeRb();
node->env.key = GetNowTime() + time;
node->cb = cb;
rbtree_insert(_rbtree, &node->env);
}
void Timer::AddZskiplistTimer(uint64_t time, CallBack cb) {
TimeNodeZp* node = new TimeNodeZp();
node->env.score = GetNowTime() + time;
node->env.level = (zskiplistLevel*)zslCreateLevel(zslRandomLevel());
node->cb = cb;
zslInsert(_zskiplist, &node->env);
}
int main(int, char**){
Timer timer(0, ZKIPLIST);
auto now = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
uint64_t timestamp_ms = duration.count();
std::cout << "Start, now time :" << timestamp_ms << std::endl;
timer.addTimer(1000, [&](void){
auto now = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
uint64_t timestamp_ms = duration.count();
std::cout << "timer 1, now time :" << timestamp_ms << std::endl;
});
timer.addTimer(2000, [&](void){
auto now = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
uint64_t timestamp_ms = duration.count();
std::cout << "timer 2, now time :" << timestamp_ms << std::endl;
});
std::thread t([&](){
timer.run();
});
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
timer.stop();
t.join();
return 0;
}
3.运行效果
完成工程代码在我的Github,欢迎自行拉倒本地测试指正哦!!!
学习参考:0voice · GitHub