A map implemented as a tree where subtrees can be shared between different maps. More...
#include <sharing_map.h>
container (which must only contain a single leaf) is not shared with any of the values in the subtree below inner. A map implemented as a tree where subtrees can be shared between different maps.
The map is implemented as a variable-height n-ary trie.
When inserting a key-value pair into the map, first the hash of its key is computed. The bits number of lower order bits of the hash are deemed significant, and are grouped into bits / chunk chunks. The hash is then treated as a string (with each chunk representing a character) for the purposes of determining the position of the key-value pair in the trie. The actual key-value pairs are stored in the leaf nodes. Collisions (i.e., two different keys yield the same "string"), are handled by chaining the corresponding key-value pairs in a std::forward_list.
The depth at which a key-value pair will be stored (when calling insert()) depends on the shortest unique prefix of its hash code (treated as a string) with respect to the hash codes of the key-value pairs already in the map.
The use of a trie in combination with hashing has the advantage that the tree is unlikely to degenerate (if the number of hash collisions is low). This makes re-balancing operations unnecessary which do not interact well with sharing. A disadvantage is that the height of the tree is likely greater than if the elements had been stored in a balanced tree.
The nodes in the sharing map are objects of type sharing_nodet. A sharing node has a shared pointer (of type small_shared_n_way_ptrt) which can point to objects of type d_internalt, d_leaft, or d_containert (representing internal nodes, leaf nodes, and container nodes, the latter being used for chaining leafs in a linked list on hash collisions).
Sharing is initially generated when a map is assigned to another map or copied via the copy constructor. Then both maps contain a pointer to the root node of the tree that represents the maps. On subsequent modifications to one of the maps, nodes are copied and sharing is lessened as described in the following.
The replace(), update(), insert(), and erase() operations interact with sharing as follows:
The replace() and update() operations are the only methods where sharing could unnecessarily be broken. This would happen when replacing an old value with a new equal value, or calling update but making no change. The sharing map provides a debug mode to detect such cases. When the template parameter fail_if_equal is set to true, then the replace() and update() methods yield an invariant violation when the new value is equal to the old value. For this to work, the type of the values stored in the map needs to have a defined equality operator (operator==).
In the descriptions of the methods of the sharing map we also give the complexity of the operations. We use the following symbols:
The first two symbols denote dynamic properties of a given map, whereas the last two symbols are static configuration parameters of the map class.
Definition at line 189 of file sharing_map.h.
Delta view of the key-value pairs in two maps.
A delta view of two maps is a view of the key-value pairs in the maps that are contained in subtrees that are not shared between them (also see get_delta_view()).
Definition at line 439 of file sharing_map.h.
Definition at line 199 of file sharing_map.h.
Definition at line 200 of file sharing_map.h.
Definition at line 196 of file sharing_map.h.
Definition at line 204 of file sharing_map.h.
Definition at line 210 of file sharing_map.h.
Definition at line 197 of file sharing_map.h.
Definition at line 207 of file sharing_map.h.
Definition at line 202 of file sharing_map.h.
Definition at line 389 of file sharing_map.h.
Definition at line 209 of file sharing_map.h.
Definition at line 253 of file sharing_map.h.
Definition at line 222 of file sharing_map.h.
Definition at line 384 of file sharing_map.h.
View of the key-value pairs in the map.
A view is a list of pairs with the components being const references to the keys and values in the map.
Definition at line 388 of file sharing_map.h.
Definition at line 192 of file sharing_map.h.
Add a delta item to the delta view if the value in the container (which must only contain a single leaf) is not shared with any of the values in the subtree below inner.
This method is called by get_delta_view() when a container containing a single leaf is encountered in the first map, and the corresponding node in the second map is an inner node.
map1.get_delta_view(map2, ...) leaf and inner must be at the same depth in their respective maps) Definition at line 860 of file sharing_map.h.
Clear map.
Definition at line 366 of file sharing_map.h.
Definition at line 702 of file sharing_map.h.
Check if map is empty.
Definition at line 360 of file sharing_map.h.
Erase element, element must exist in map.
Complexity:
Definition at line 1203 of file sharing_map.h.
Erase element if it exists.
Complexity:
Definition at line 274 of file sharing_map.h.
Find element.
Complexity:
Definition at line 1451 of file sharing_map.h.
Definition at line 851 of file sharing_map.h.
Definition at line 1122 of file sharing_map.h.
Get a delta view of the elements in the map.
Informally, a delta view of two maps is a view of the key-value pairs in the maps that are contained in subtrees that are not shared between them.
A delta view is represented as a list of structs, with each struct having three members (key, value1, value2). The elements key, value1, and value2 are const references to the corresponding elements in the map, with the third being absent if the key only existed in the queried map. The first element is the key, the second element is the mapped value of the first map, and the third element is the mapped value of the second map if present.
Calling A.delta_view(B, ...) yields a view such that for each element in the view one of two things holds:
When only_common=true, the first case above holds for every element in the view.
Complexity:
The symbols N1, M1 refer to map A, and symbols N2, M2 refer to map B.
Definition at line 939 of file sharing_map.h.
Definition at line 1131 of file sharing_map.h.
Definition at line 1163 of file sharing_map.h.
[](const Iterator it) -> sharing_mapt< keyT, valueT, fail_if_equal, hashT, equalT > & { return *it; }
Get sharing stats.
Complexity:
Definition at line 784 of file sharing_map.h.
Get sharing stats.
Complexity:
Definition at line 829 of file sharing_map.h.
Convenience function to get a sorted view of the map elements.
A view is a list of pairs with the components being const references to the keys and values in the map.
Definition at line 462 of file sharing_map.h.
Definition at line 452 of file sharing_map.h.
Get a view of the elements in the map A view is a list of pairs with the components being const references to the keys and values in the map.
Complexity:
Definition at line 836 of file sharing_map.h.
Check if key is in map.
Complexity:
Definition at line 377 of file sharing_map.h.
Insert element, element must not exist in map.
Complexity:
Definition at line 1348 of file sharing_map.h.
Definition at line 292 of file sharing_map.h.
Definition at line 396 of file sharing_map.h.
Definition at line 391 of file sharing_map.h.
Definition at line 656 of file sharing_map.h.
Call a function for every key-value pair in the map.
Complexity: as sharing_mapt::get_view
Definition at line 515 of file sharing_map.h.
Move a leaf node further down the tree such as to resolve a collision with another key-value pair.
This method is called by insert() to resolve a collision between a key-value pair to be newly inserted, and a key-value pair existing in the map.
chunk * starting_level bits (i.e., key_suffix is the rest of the hash code used to determine the position of the key-value pair below level starting_level inner[bit_last] points to the leaf node to move further down the tree) inner[bit_last] is the leaf node to move further down the tree Definition at line 1270 of file sharing_map.h.
Replace element, element must exist in map.
Complexity:
Definition at line 1425 of file sharing_map.h.
Update an element in place; element must exist in map.
Rationale: this avoids copy-out / edit / replace sequences without leaking a non-const reference
Complexity: as sharing_mapt::replace
Definition at line 1437 of file sharing_map.h.
Definition at line 641 of file sharing_map.h.
Definition at line 642 of file sharing_map.h.
Definition at line 638 of file sharing_map.h.
Definition at line 646 of file sharing_map.h.
Definition at line 649 of file sharing_map.h.
Definition at line 645 of file sharing_map.h.
Definition at line 652 of file sharing_map.h.