skiplist.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #include"basical/type_checking.h"
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<exception>
  5. #include<random>
  6. #include<shared_mutex>
  7. #include <variant>
  8. namespace nanxing_extend
  9. {
  10. //错误处理机制
  11. class nextpoint_new:std::exception //skip_node分配空间失败的时候
  12. {
  13. const char* what() const noexcept
  14. {
  15. return "malloc next_node point fault";
  16. }
  17. };
  18. class newNode_error:std::exception //申请新的空间的时候
  19. {
  20. const char* what() const noexcept
  21. {
  22. return "malloc new node error";
  23. }
  24. };
  25. class random_error:std::exception //申请预设随机数空间的时候
  26. {
  27. const char* what() const noexcept
  28. {
  29. return "malloc random space error";
  30. }
  31. };
  32. enum class Skip_result //跳表操作的结果
  33. {
  34. successufl,
  35. #ifdef SKIP_MAX_SIZE
  36. full,
  37. #endif
  38. #ifdef SKIP_MAX_SIZE
  39. too_small,
  40. #endif
  41. fault,
  42. exit
  43. };
  44. //注意这里的V只能是要么是能直接深拷贝的类型,要么是指向堆上数据的指针类型
  45. template<typename K,typename V>
  46. struct skip_node
  47. {
  48. static_assert(nanxing_extend::compare_admit<K>value);
  49. static_assert(nanxing_extend::compare_admit<V>value);
  50. skip_node<K,V>** next_node;
  51. V value;
  52. private:
  53. K key;
  54. int level;
  55. public:
  56. skip_node(){};
  57. skip_node(K _key,V _value,int _level):key(_key),value(_value),level(_level){};
  58. init_next(int level)
  59. {
  60. try
  61. {
  62. next_node=::new (skip_node<K,V>*)[level];
  63. }
  64. catch(std::bad_alloc){ //捕获内存分配错误
  65. throw nextpoint_new(); //重新抛出一个定制的更详细的类型用以明确错误的具体位置
  66. }
  67. std::memset(next_node,0,sizeof(skip_node<K,V>*)*level);
  68. }
  69. K get_key(){ return key; }
  70. };
  71. template<typename K,typename V>
  72. class skipList
  73. {
  74. static_assert(nanxing_extend::compare_admit<K>value);
  75. static_assert(nanxing_extend::compare_admit<V>value);
  76. private:
  77. using Node=skip_node<K,V>;
  78. using ptr=Node*;
  79. using Nptr=Node**;
  80. //由于C++的便利性我们考虑使用带头节点的跳表(C++允许对数据不进行初始化(默认构造函数))
  81. #ifdef NANXING_THREAD_
  82. std::shared_mutex RW_lock; //读写锁
  83. #endif
  84. Nptr head; //头节点
  85. int max_level; //最大高度
  86. int* random_level;
  87. int current_level; //跳表当前高度
  88. int current_size; //跳表当前尺寸
  89. //这里出于一个考虑,当跳表单纯作为小数据内存数据库,单表大小限制是没有意义的
  90. //但是像level_db这样作为KV数据库的缓存的时候,就需要限制大小进行落盘
  91. #ifdef SKIP_MAX_SIZE
  92. int max_size; //跳表允许的最大尺寸
  93. #endif
  94. public:
  95. #ifndef SKIP_MAX_SIZE
  96. skipList(int _max_level):max_level(_max_level),random_level(nullptr)
  97. {
  98. try
  99. {
  100. Node* middle=::new skip_node;
  101. middle->init_next(max_level);
  102. head=::new (Node*)[max_level];
  103. for(auto& i in head)
  104. {
  105. i=middle;
  106. }
  107. }
  108. catch(std::bad_alloc)
  109. {
  110. throw newNode_error(); //重新抛出更详细的错误类型
  111. }
  112. }
  113. #elif
  114. skipList(int _max_level,int _max_size):max_size(_max_size),max_level(_max_level),random_level(nullptr)
  115. {
  116. try
  117. {
  118. Node* middle=::new skip_node;
  119. middle->init_next(max_level);
  120. head=::new (Node*)[max_level];
  121. for(auto& i in head)
  122. {
  123. i=middle;
  124. }
  125. }
  126. catch(std::bad_alloc)
  127. {
  128. throw newNode_error();
  129. }
  130. }
  131. #endif
  132. [[nodiscard]] //这个返回值最好不要忽略否则很有可能会出现内存泄漏
  133. auto insert(K _key,V _value)->std::variant<Skip_result,V> //如果相同的时候我们考虑将value返回因为value很可能会是一个指针,需要手动清空内存
  134. {
  135. #ifdef NANXING_THREAD_
  136. std::lock_guard<std::shared_mutex> lock(RW_lock);
  137. #endif
  138. std::variant<Skip_result,V> sk;
  139. #ifdef SKIP_MAX_SIZE
  140. if(current_size==max_size)
  141. {
  142. return sk=Skip_result::full;
  143. }
  144. #endif
  145. int rand_level=0;
  146. ptr updata[max_level]={nullptr}; //用于更新的数组
  147. int level=current_level-1;
  148. ptr point=head[level];
  149. ptr new_node;
  150. for(int i=level;i>=0;i--)
  151. {
  152. for(;;)
  153. {
  154. if(point->next_node[level]==nullptr)
  155. {
  156. updata[level]=point;
  157. break;
  158. }
  159. else if(point->next_node[level]->key>=_key)
  160. {
  161. if(point->next_node[level]->key==_key)
  162. {
  163. sk=std::move(point->next_node[level]->value); //这个值已经不需要了,直接移动
  164. point->next_node[level]->value=_value;
  165. return sk;
  166. }
  167. else
  168. {
  169. updata[level]=point;
  170. break;
  171. }
  172. else{
  173. point=point->head[level]; //更新point指针
  174. }
  175. }
  176. }
  177. [[likely]]
  178. if(random_level!=nullptr)
  179. {
  180. rand_level=random_level[current_size%1024];
  181. new_node=new skip_node(_key,_value,rand_level);
  182. }
  183. [[unlikely]]
  184. else
  185. {
  186. rand_level=std::rand(chrono::system_clock::now().time_since_epoch().count())%(1+max_level);
  187. new_node=new skip_node(_key,_value,rand_level);
  188. }
  189. ptr tmp=nullptr;
  190. for(int i=0;i<=rand_level;i++)
  191. {
  192. tmp=updata[i]->next_node[i];
  193. updata[i]->next_node[i]=new_node;
  194. new_node->next_node[i]=tmp;
  195. }
  196. if(rand_level>current_level)
  197. {
  198. current_level=rand_level;
  199. }
  200. current_size++;
  201. }
  202. sk=Skip_result::successufl;
  203. }
  204. [[nodiscard]]
  205. auto search(K _key)->std::variant<Skip_result,V> noexcept //不涉及任何内存分配相关任务,因此是异常安全的
  206. {
  207. #ifdef NANXING_THREAD_
  208. std::shared_lock<std::shared_mutex> lock(RW_lock);
  209. #endif
  210. std::variant<Skip_result,V> sk;
  211. ptr tmp=head[current_level-1];
  212. int tmp_level=current_level-1;
  213. for(i=tmp_level;i>=0;i--)
  214. {
  215. while(tmp->next_node[tmp_level]!=nullptr)
  216. {
  217. if(tmp->next_node[tmp_level]->key>=_key)
  218. {
  219. if(tmp->next_node[tmp_level]->key==_key)
  220. {
  221. return sk=Skip_result::exit;
  222. }
  223. else{
  224. break; //跳出开始下一层循环
  225. }
  226. }
  227. else{
  228. tmp=tmp->next_node[tmp_level];
  229. }
  230. }
  231. }
  232. return sk=Skip_result::fault;
  233. }
  234. void init_skip() //直接生成随机数表
  235. {
  236. #ifdef NANXING_THREAD_
  237. std::lock_guard<std::shared_mutex> lock(RW_lock);
  238. #endif
  239. if(random_level!=nullptr)
  240. {
  241. return;
  242. }
  243. try{
  244. random_level=new int[1024]; //刚好是一页的大小(4KB)
  245. }
  246. catch(std::bad_alloc)
  247. {
  248. throw random_error();
  249. }
  250. std::mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
  251. for(auto& i :random_level)
  252. {
  253. i=(rnd()%max_level)+1;
  254. }
  255. }
  256. };
  257. #ifdef SKIP_MAX_SIZE
  258. [[nodicard]]
  259. auto change_size(int _max_size)->std::variant<Skip_result,V> noexcept
  260. {
  261. std::variant<
  262. if(_max_size>this->max_size)
  263. {
  264. this->max_size=_max_size;
  265. tmp=Skip_result::successufl;
  266. return tmp;
  267. }
  268. else
  269. {
  270. tmp=Skip_result::too_samll;
  271. return tmp;
  272. }
  273. }
  274. #endif
  275. }