move_to_front.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. // Copyright (c) 2017 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #ifndef SOURCE_COMP_MOVE_TO_FRONT_H_
  15. #define SOURCE_COMP_MOVE_TO_FRONT_H_
  16. #include <cassert>
  17. #include <cstdint>
  18. #include <map>
  19. #include <set>
  20. #include <unordered_map>
  21. #include <vector>
  22. namespace spvtools {
  23. namespace comp {
  24. // Log(n) move-to-front implementation. Implements the following functions:
  25. // Insert - pushes value to the front of the mtf sequence
  26. // (only unique values allowed).
  27. // Remove - remove value from the sequence.
  28. // ValueFromRank - access value by its 1-indexed rank in the sequence.
  29. // RankFromValue - get the rank of the given value in the sequence.
  30. // Accessing a value with ValueFromRank or RankFromValue moves the value to the
  31. // front of the sequence (rank of 1).
  32. //
  33. // The implementation is based on an AVL-based order statistic tree. The tree
  34. // is ordered by timestamps issued when values are inserted or accessed (recent
  35. // values go to the left side of the tree, old values are gradually rotated to
  36. // the right side).
  37. //
  38. // Terminology
  39. // rank: 1-indexed rank showing how recently the value was inserted or accessed.
  40. // node: handle used internally to access node data.
  41. // size: size of the subtree of a node (including the node).
  42. // height: distance from a node to the farthest leaf.
  43. class MoveToFront {
  44. public:
  45. explicit MoveToFront(size_t reserve_capacity = 4) {
  46. nodes_.reserve(reserve_capacity);
  47. // Create NIL node.
  48. nodes_.emplace_back(Node());
  49. }
  50. virtual ~MoveToFront() = default;
  51. // Inserts value in the move-to-front sequence. Does nothing if the value is
  52. // already in the sequence. Returns true if insertion was successful.
  53. // The inserted value is placed at the front of the sequence (rank 1).
  54. bool Insert(uint32_t value);
  55. // Removes value from move-to-front sequence. Returns false iff the value
  56. // was not found.
  57. bool Remove(uint32_t value);
  58. // Computes 1-indexed rank of value in the move-to-front sequence and moves
  59. // the value to the front. Example:
  60. // Before the call: 4 8 2 1 7
  61. // RankFromValue(8) returns 2
  62. // After the call: 8 4 2 1 7
  63. // Returns true iff the value was found in the sequence.
  64. bool RankFromValue(uint32_t value, uint32_t* rank);
  65. // Returns value corresponding to a 1-indexed rank in the move-to-front
  66. // sequence and moves the value to the front. Example:
  67. // Before the call: 4 8 2 1 7
  68. // ValueFromRank(2) returns 8
  69. // After the call: 8 4 2 1 7
  70. // Returns true iff the rank is within bounds [1, GetSize()].
  71. bool ValueFromRank(uint32_t rank, uint32_t* value);
  72. // Moves the value to the front of the sequence.
  73. // Returns false iff value is not in the sequence.
  74. bool Promote(uint32_t value);
  75. // Returns true iff the move-to-front sequence contains the value.
  76. bool HasValue(uint32_t value) const;
  77. // Returns the number of elements in the move-to-front sequence.
  78. uint32_t GetSize() const { return SizeOf(root_); }
  79. protected:
  80. // Internal tree data structure uses handles instead of pointers. Leaves and
  81. // root parent reference a singleton under handle 0. Although dereferencing
  82. // a null pointer is not possible, inappropriate access to handle 0 would
  83. // cause an assertion. Handles are not garbage collected if value was
  84. // deprecated
  85. // with DeprecateValue(). But handles are recycled when a node is
  86. // repositioned.
  87. // Internal tree data structure node.
  88. struct Node {
  89. // Timestamp from a logical clock which updates every time the element is
  90. // accessed through ValueFromRank or RankFromValue.
  91. uint32_t timestamp = 0;
  92. // The size of the node's subtree, including the node.
  93. // SizeOf(LeftOf(node)) + SizeOf(RightOf(node)) + 1.
  94. uint32_t size = 0;
  95. // Handles to connected nodes.
  96. uint32_t left = 0;
  97. uint32_t right = 0;
  98. uint32_t parent = 0;
  99. // Distance to the farthest leaf.
  100. // Leaves have height 0, real nodes at least 1.
  101. uint32_t height = 0;
  102. // Stored value.
  103. uint32_t value = 0;
  104. };
  105. // Creates node and sets correct values. Non-NIL nodes should be created only
  106. // through this function. If the node with this value has been created
  107. // previously
  108. // and since orphaned, reuses the old node instead of creating a new one.
  109. uint32_t CreateNode(uint32_t timestamp, uint32_t value);
  110. // Node accessor methods. Naming is designed to be similar to natural
  111. // language as these functions tend to be used in sequences, for example:
  112. // ParentOf(LeftestDescendentOf(RightOf(node)))
  113. // Returns value of the node referenced by |handle|.
  114. uint32_t ValueOf(uint32_t node) const { return nodes_.at(node).value; }
  115. // Returns left child of |node|.
  116. uint32_t LeftOf(uint32_t node) const { return nodes_.at(node).left; }
  117. // Returns right child of |node|.
  118. uint32_t RightOf(uint32_t node) const { return nodes_.at(node).right; }
  119. // Returns parent of |node|.
  120. uint32_t ParentOf(uint32_t node) const { return nodes_.at(node).parent; }
  121. // Returns timestamp of |node|.
  122. uint32_t TimestampOf(uint32_t node) const {
  123. assert(node);
  124. return nodes_.at(node).timestamp;
  125. }
  126. // Returns size of |node|.
  127. uint32_t SizeOf(uint32_t node) const { return nodes_.at(node).size; }
  128. // Returns height of |node|.
  129. uint32_t HeightOf(uint32_t node) const { return nodes_.at(node).height; }
  130. // Returns mutable reference to value of |node|.
  131. uint32_t& MutableValueOf(uint32_t node) {
  132. assert(node);
  133. return nodes_.at(node).value;
  134. }
  135. // Returns mutable reference to handle of left child of |node|.
  136. uint32_t& MutableLeftOf(uint32_t node) {
  137. assert(node);
  138. return nodes_.at(node).left;
  139. }
  140. // Returns mutable reference to handle of right child of |node|.
  141. uint32_t& MutableRightOf(uint32_t node) {
  142. assert(node);
  143. return nodes_.at(node).right;
  144. }
  145. // Returns mutable reference to handle of parent of |node|.
  146. uint32_t& MutableParentOf(uint32_t node) {
  147. assert(node);
  148. return nodes_.at(node).parent;
  149. }
  150. // Returns mutable reference to timestamp of |node|.
  151. uint32_t& MutableTimestampOf(uint32_t node) {
  152. assert(node);
  153. return nodes_.at(node).timestamp;
  154. }
  155. // Returns mutable reference to size of |node|.
  156. uint32_t& MutableSizeOf(uint32_t node) {
  157. assert(node);
  158. return nodes_.at(node).size;
  159. }
  160. // Returns mutable reference to height of |node|.
  161. uint32_t& MutableHeightOf(uint32_t node) {
  162. assert(node);
  163. return nodes_.at(node).height;
  164. }
  165. // Returns true iff |node| is left child of its parent.
  166. bool IsLeftChild(uint32_t node) const {
  167. assert(node);
  168. return LeftOf(ParentOf(node)) == node;
  169. }
  170. // Returns true iff |node| is right child of its parent.
  171. bool IsRightChild(uint32_t node) const {
  172. assert(node);
  173. return RightOf(ParentOf(node)) == node;
  174. }
  175. // Returns true iff |node| has no relatives.
  176. bool IsOrphan(uint32_t node) const {
  177. assert(node);
  178. return !ParentOf(node) && !LeftOf(node) && !RightOf(node);
  179. }
  180. // Returns true iff |node| is in the tree.
  181. bool IsInTree(uint32_t node) const {
  182. assert(node);
  183. return node == root_ || !IsOrphan(node);
  184. }
  185. // Returns the height difference between right and left subtrees.
  186. int BalanceOf(uint32_t node) const {
  187. return int(HeightOf(RightOf(node))) - int(HeightOf(LeftOf(node)));
  188. }
  189. // Updates size and height of the node, assuming that the children have
  190. // correct values.
  191. void UpdateNode(uint32_t node);
  192. // Returns the most LeftOf(LeftOf(... descendent which is not leaf.
  193. uint32_t LeftestDescendantOf(uint32_t node) const {
  194. uint32_t parent = 0;
  195. while (node) {
  196. parent = node;
  197. node = LeftOf(node);
  198. }
  199. return parent;
  200. }
  201. // Returns the most RightOf(RightOf(... descendent which is not leaf.
  202. uint32_t RightestDescendantOf(uint32_t node) const {
  203. uint32_t parent = 0;
  204. while (node) {
  205. parent = node;
  206. node = RightOf(node);
  207. }
  208. return parent;
  209. }
  210. // Inserts node in the tree. The node must be an orphan.
  211. void InsertNode(uint32_t node);
  212. // Removes node from the tree. May change value_to_node_ if removal uses a
  213. // scapegoat. Returns the removed (orphaned) handle for recycling. The
  214. // returned handle may not be equal to |node| if scapegoat was used.
  215. uint32_t RemoveNode(uint32_t node);
  216. // Rotates |node| left, reassigns all connections and returns the node
  217. // which takes place of the |node|.
  218. uint32_t RotateLeft(const uint32_t node);
  219. // Rotates |node| right, reassigns all connections and returns the node
  220. // which takes place of the |node|.
  221. uint32_t RotateRight(const uint32_t node);
  222. // Root node handle. The tree is empty if root_ is 0.
  223. uint32_t root_ = 0;
  224. // Incremented counters for next timestamp and value.
  225. uint32_t next_timestamp_ = 1;
  226. // Holds all tree nodes. Indices of this vector are node handles.
  227. std::vector<Node> nodes_;
  228. // Maps ids to node handles.
  229. std::unordered_map<uint32_t, uint32_t> value_to_node_;
  230. // Cache for the last accessed value in the sequence.
  231. uint32_t last_accessed_value_ = 0;
  232. bool last_accessed_value_valid_ = false;
  233. };
  234. class MultiMoveToFront {
  235. public:
  236. // Inserts |value| to sequence with handle |mtf|.
  237. // Returns false if |mtf| already has |value|.
  238. bool Insert(uint64_t mtf, uint32_t value) {
  239. if (GetMtf(mtf).Insert(value)) {
  240. val_to_mtfs_[value].insert(mtf);
  241. return true;
  242. }
  243. return false;
  244. }
  245. // Removes |value| from sequence with handle |mtf|.
  246. // Returns false if |mtf| doesn't have |value|.
  247. bool Remove(uint64_t mtf, uint32_t value) {
  248. if (GetMtf(mtf).Remove(value)) {
  249. val_to_mtfs_[value].erase(mtf);
  250. return true;
  251. }
  252. assert(val_to_mtfs_[value].count(mtf) == 0);
  253. return false;
  254. }
  255. // Removes |value| from all sequences which have it.
  256. void RemoveFromAll(uint32_t value) {
  257. auto it = val_to_mtfs_.find(value);
  258. if (it == val_to_mtfs_.end()) return;
  259. auto& mtfs_containing_value = it->second;
  260. for (uint64_t mtf : mtfs_containing_value) {
  261. GetMtf(mtf).Remove(value);
  262. }
  263. val_to_mtfs_.erase(value);
  264. }
  265. // Computes rank of |value| in sequence |mtf|.
  266. // Returns false if |mtf| doesn't have |value|.
  267. bool RankFromValue(uint64_t mtf, uint32_t value, uint32_t* rank) {
  268. return GetMtf(mtf).RankFromValue(value, rank);
  269. }
  270. // Finds |value| with |rank| in sequence |mtf|.
  271. // Returns false if |rank| is out of bounds.
  272. bool ValueFromRank(uint64_t mtf, uint32_t rank, uint32_t* value) {
  273. return GetMtf(mtf).ValueFromRank(rank, value);
  274. }
  275. // Returns size of |mtf| sequence.
  276. uint32_t GetSize(uint64_t mtf) { return GetMtf(mtf).GetSize(); }
  277. // Promotes |value| in all sequences which have it.
  278. void Promote(uint32_t value) {
  279. const auto it = val_to_mtfs_.find(value);
  280. if (it == val_to_mtfs_.end()) return;
  281. const auto& mtfs_containing_value = it->second;
  282. for (uint64_t mtf : mtfs_containing_value) {
  283. GetMtf(mtf).Promote(value);
  284. }
  285. }
  286. // Inserts |value| in sequence |mtf| or promotes if it's already there.
  287. void InsertOrPromote(uint64_t mtf, uint32_t value) {
  288. if (!Insert(mtf, value)) {
  289. GetMtf(mtf).Promote(value);
  290. }
  291. }
  292. // Returns if |mtf| sequence has |value|.
  293. bool HasValue(uint64_t mtf, uint32_t value) {
  294. return GetMtf(mtf).HasValue(value);
  295. }
  296. private:
  297. // Returns actual MoveToFront object corresponding to |handle|.
  298. // As multiple operations are often performed consecutively for the same
  299. // sequence, the last returned value is cached.
  300. MoveToFront& GetMtf(uint64_t handle) {
  301. if (!cached_mtf_ || cached_handle_ != handle) {
  302. cached_handle_ = handle;
  303. cached_mtf_ = &mtfs_[handle];
  304. }
  305. return *cached_mtf_;
  306. }
  307. // Container holding MoveToFront objects. Map key is sequence handle.
  308. std::map<uint64_t, MoveToFront> mtfs_;
  309. // Container mapping value to sequences which contain that value.
  310. std::unordered_map<uint32_t, std::set<uint64_t>> val_to_mtfs_;
  311. // Cache for the last accessed sequence.
  312. uint64_t cached_handle_ = 0;
  313. MoveToFront* cached_mtf_ = nullptr;
  314. };
  315. } // namespace comp
  316. } // namespace spvtools
  317. #endif // SOURCE_COMP_MOVE_TO_FRONT_H_