小组成员:谢瑞阳、徐翔宇
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

379 lignes
11 KiB

  1. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  4. //
  5. // Thread safety
  6. // -------------
  7. //
  8. // Writes require external synchronization, most likely a mutex.
  9. // Reads require a guarantee that the SkipList will not be destroyed
  10. // while the read is in progress. Apart from that, reads progress
  11. // without any internal locking or synchronization.
  12. //
  13. // Invariants:
  14. //
  15. // (1) Allocated nodes are never deleted until the SkipList is
  16. // destroyed. This is trivially guaranteed by the code since we
  17. // never delete any skip list nodes.
  18. //
  19. // (2) The contents of a Node except for the next/prev pointers are
  20. // immutable after the Node has been linked into the SkipList.
  21. // Only Insert() modifies the list, and it is careful to initialize
  22. // a node and use release-stores to publish the nodes in one or
  23. // more lists.
  24. //
  25. // ... prev vs. next pointer ordering ...
  26. #include <assert.h>
  27. #include <stdlib.h>
  28. #include "port/port.h"
  29. #include "util/arena.h"
  30. #include "util/random.h"
  31. namespace leveldb {
  32. class Arena;
  33. template<typename Key, class Comparator>
  34. class SkipList {
  35. private:
  36. struct Node;
  37. public:
  38. // Create a new SkipList object that will use "cmp" for comparing keys,
  39. // and will allocate memory using "*arena". Objects allocated in the arena
  40. // must remain allocated for the lifetime of the skiplist object.
  41. explicit SkipList(Comparator cmp, Arena* arena);
  42. // Insert key into the list.
  43. // REQUIRES: nothing that compares equal to key is currently in the list.
  44. void Insert(const Key& key);
  45. // Returns true iff an entry that compares equal to key is in the list.
  46. bool Contains(const Key& key) const;
  47. // Iteration over the contents of a skip list
  48. class Iterator {
  49. public:
  50. // Initialize an iterator over the specified list.
  51. // The returned iterator is not valid.
  52. explicit Iterator(const SkipList* list);
  53. // Returns true iff the iterator is positioned at a valid node.
  54. bool Valid() const;
  55. // Returns the key at the current position.
  56. // REQUIRES: Valid()
  57. const Key& key() const;
  58. // Advances to the next position.
  59. // REQUIRES: Valid()
  60. void Next();
  61. // Advances to the previous position.
  62. // REQUIRES: Valid()
  63. void Prev();
  64. // Advance to the first entry with a key >= target
  65. void Seek(const Key& target);
  66. // Position at the first entry in list.
  67. // Final state of iterator is Valid() iff list is not empty.
  68. void SeekToFirst();
  69. // Position at the last entry in list.
  70. // Final state of iterator is Valid() iff list is not empty.
  71. void SeekToLast();
  72. private:
  73. const SkipList* list_;
  74. Node* node_;
  75. // Intentionally copyable
  76. };
  77. private:
  78. enum { kMaxHeight = 12 };
  79. // Immutable after construction
  80. Comparator const compare_;
  81. Arena* const arena_; // Arena used for allocations of nodes
  82. Node* const head_;
  83. // Modified only by Insert(). Read racily by readers, but stale
  84. // values are ok.
  85. port::AtomicPointer max_height_; // Height of the entire list
  86. inline int GetMaxHeight() const {
  87. return static_cast<int>(
  88. reinterpret_cast<intptr_t>(max_height_.NoBarrier_Load()));
  89. }
  90. // Read/written only by Insert().
  91. Random rnd_;
  92. Node* NewNode(const Key& key, int height);
  93. int RandomHeight();
  94. bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); }
  95. // Return true if key is greater than the data stored in "n"
  96. bool KeyIsAfterNode(const Key& key, Node* n) const;
  97. // Return the earliest node that comes at or after key.
  98. // Return NULL if there is no such node.
  99. //
  100. // If prev is non-NULL, fills prev[level] with pointer to previous
  101. // node at "level" for every level in [0..max_height_-1].
  102. Node* FindGreaterOrEqual(const Key& key, Node** prev) const;
  103. // Return the latest node with a key < key.
  104. // Return head_ if there is no such node.
  105. Node* FindLessThan(const Key& key) const;
  106. // Return the last node in the list.
  107. // Return head_ if list is empty.
  108. Node* FindLast() const;
  109. // No copying allowed
  110. SkipList(const SkipList&);
  111. void operator=(const SkipList&);
  112. };
  113. // Implementation details follow
  114. template<typename Key, class Comparator>
  115. struct SkipList<Key,Comparator>::Node {
  116. explicit Node(const Key& k) : key(k) { }
  117. Key const key;
  118. // Accessors/mutators for links. Wrapped in methods so we can
  119. // add the appropriate barriers as necessary.
  120. Node* Next(int n) {
  121. assert(n >= 0);
  122. // Use an 'acquire load' so that we observe a fully initialized
  123. // version of the returned Node.
  124. return reinterpret_cast<Node*>(next_[n].Acquire_Load());
  125. }
  126. void SetNext(int n, Node* x) {
  127. assert(n >= 0);
  128. // Use a 'release store' so that anybody who reads through this
  129. // pointer observes a fully initialized version of the inserted node.
  130. next_[n].Release_Store(x);
  131. }
  132. // No-barrier variants that can be safely used in a few locations.
  133. Node* NoBarrier_Next(int n) {
  134. assert(n >= 0);
  135. return reinterpret_cast<Node*>(next_[n].NoBarrier_Load());
  136. }
  137. void NoBarrier_SetNext(int n, Node* x) {
  138. assert(n >= 0);
  139. next_[n].NoBarrier_Store(x);
  140. }
  141. private:
  142. // Array of length equal to the node height. next_[0] is lowest level link.
  143. port::AtomicPointer next_[1];
  144. };
  145. template<typename Key, class Comparator>
  146. typename SkipList<Key,Comparator>::Node*
  147. SkipList<Key,Comparator>::NewNode(const Key& key, int height) {
  148. char* mem = arena_->AllocateAligned(
  149. sizeof(Node) + sizeof(port::AtomicPointer) * (height - 1));
  150. return new (mem) Node(key);
  151. }
  152. template<typename Key, class Comparator>
  153. inline SkipList<Key,Comparator>::Iterator::Iterator(const SkipList* list) {
  154. list_ = list;
  155. node_ = NULL;
  156. }
  157. template<typename Key, class Comparator>
  158. inline bool SkipList<Key,Comparator>::Iterator::Valid() const {
  159. return node_ != NULL;
  160. }
  161. template<typename Key, class Comparator>
  162. inline const Key& SkipList<Key,Comparator>::Iterator::key() const {
  163. assert(Valid());
  164. return node_->key;
  165. }
  166. template<typename Key, class Comparator>
  167. inline void SkipList<Key,Comparator>::Iterator::Next() {
  168. assert(Valid());
  169. node_ = node_->Next(0);
  170. }
  171. template<typename Key, class Comparator>
  172. inline void SkipList<Key,Comparator>::Iterator::Prev() {
  173. // Instead of using explicit "prev" links, we just search for the
  174. // last node that falls before key.
  175. assert(Valid());
  176. node_ = list_->FindLessThan(node_->key);
  177. if (node_ == list_->head_) {
  178. node_ = NULL;
  179. }
  180. }
  181. template<typename Key, class Comparator>
  182. inline void SkipList<Key,Comparator>::Iterator::Seek(const Key& target) {
  183. node_ = list_->FindGreaterOrEqual(target, NULL);
  184. }
  185. template<typename Key, class Comparator>
  186. inline void SkipList<Key,Comparator>::Iterator::SeekToFirst() {
  187. node_ = list_->head_->Next(0);
  188. }
  189. template<typename Key, class Comparator>
  190. inline void SkipList<Key,Comparator>::Iterator::SeekToLast() {
  191. node_ = list_->FindLast();
  192. if (node_ == list_->head_) {
  193. node_ = NULL;
  194. }
  195. }
  196. template<typename Key, class Comparator>
  197. int SkipList<Key,Comparator>::RandomHeight() {
  198. // Increase height with probability 1 in kBranching
  199. static const unsigned int kBranching = 4;
  200. int height = 1;
  201. while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) {
  202. height++;
  203. }
  204. assert(height > 0);
  205. assert(height <= kMaxHeight);
  206. return height;
  207. }
  208. template<typename Key, class Comparator>
  209. bool SkipList<Key,Comparator>::KeyIsAfterNode(const Key& key, Node* n) const {
  210. // NULL n is considered infinite
  211. return (n != NULL) && (compare_(n->key, key) < 0);
  212. }
  213. template<typename Key, class Comparator>
  214. typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOrEqual(const Key& key, Node** prev)
  215. const {
  216. Node* x = head_;
  217. int level = GetMaxHeight() - 1;
  218. while (true) {
  219. Node* next = x->Next(level);
  220. if (KeyIsAfterNode(key, next)) {
  221. // Keep searching in this list
  222. x = next;
  223. } else {
  224. if (prev != NULL) prev[level] = x;
  225. if (level == 0) {
  226. return next;
  227. } else {
  228. // Switch to next list
  229. level--;
  230. }
  231. }
  232. }
  233. }
  234. template<typename Key, class Comparator>
  235. typename SkipList<Key,Comparator>::Node*
  236. SkipList<Key,Comparator>::FindLessThan(const Key& key) const {
  237. Node* x = head_;
  238. int level = GetMaxHeight() - 1;
  239. while (true) {
  240. assert(x == head_ || compare_(x->key, key) < 0);
  241. Node* next = x->Next(level);
  242. if (next == NULL || compare_(next->key, key) >= 0) {
  243. if (level == 0) {
  244. return x;
  245. } else {
  246. // Switch to next list
  247. level--;
  248. }
  249. } else {
  250. x = next;
  251. }
  252. }
  253. }
  254. template<typename Key, class Comparator>
  255. typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindLast()
  256. const {
  257. Node* x = head_;
  258. int level = GetMaxHeight() - 1;
  259. while (true) {
  260. Node* next = x->Next(level);
  261. if (next == NULL) {
  262. if (level == 0) {
  263. return x;
  264. } else {
  265. // Switch to next list
  266. level--;
  267. }
  268. } else {
  269. x = next;
  270. }
  271. }
  272. }
  273. template<typename Key, class Comparator>
  274. SkipList<Key,Comparator>::SkipList(Comparator cmp, Arena* arena)
  275. : compare_(cmp),
  276. arena_(arena),
  277. head_(NewNode(0 /* any key will do */, kMaxHeight)),
  278. max_height_(reinterpret_cast<void*>(1)),
  279. rnd_(0xdeadbeef) {
  280. for (int i = 0; i < kMaxHeight; i++) {
  281. head_->SetNext(i, NULL);
  282. }
  283. }
  284. template<typename Key, class Comparator>
  285. void SkipList<Key,Comparator>::Insert(const Key& key) {
  286. // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual()
  287. // here since Insert() is externally synchronized.
  288. Node* prev[kMaxHeight];
  289. Node* x = FindGreaterOrEqual(key, prev);
  290. // Our data structure does not allow duplicate insertion
  291. assert(x == NULL || !Equal(key, x->key));
  292. int height = RandomHeight();
  293. if (height > GetMaxHeight()) {
  294. for (int i = GetMaxHeight(); i < height; i++) {
  295. prev[i] = head_;
  296. }
  297. //fprintf(stderr, "Change height from %d to %d\n", max_height_, height);
  298. // It is ok to mutate max_height_ without any synchronization
  299. // with concurrent readers. A concurrent reader that observes
  300. // the new value of max_height_ will see either the old value of
  301. // new level pointers from head_ (NULL), or a new value set in
  302. // the loop below. In the former case the reader will
  303. // immediately drop to the next level since NULL sorts after all
  304. // keys. In the latter case the reader will use the new node.
  305. max_height_.NoBarrier_Store(reinterpret_cast<void*>(height));
  306. }
  307. x = NewNode(key, height);
  308. for (int i = 0; i < height; i++) {
  309. // NoBarrier_SetNext() suffices since we will add a barrier when
  310. // we publish a pointer to "x" in prev[i].
  311. x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i));
  312. prev[i]->SetNext(i, x);
  313. }
  314. }
  315. template<typename Key, class Comparator>
  316. bool SkipList<Key,Comparator>::Contains(const Key& key) const {
  317. Node* x = FindGreaterOrEqual(key, NULL);
  318. if (x != NULL && Equal(key, x->key)) {
  319. return true;
  320. } else {
  321. return false;
  322. }
  323. }
  324. } // namespace leveldb