![]() |
Arene Base
Fundamental Utilities For Safety Critical C++
|
The intrusive sub-package provides containers that use fields in the stored elements themselves to link them into the data structure, thus avoid dynamic memory allocation.
The public headers are
The Bazel target is
Most containers, such as those in the standard library or in other libraries such as inline_container are non-intrusive. This means that they internally manage memory for the elements they hold, and consume copies of elements when they are inserted. In general, any element can be placed into a non-intrusive container without modification. This style of container is thus easy to use and difficult to use wrong, but comes with the tradeoff of needing to copy elements into and out of it, as well as needing to allocate memory on construction and on growth if the container supports growing.
In comparison, an intrusive container does not manage any storage for holding its elements. Instead, the elements themselves are modified with additional content, colloquially called hooks, needed to support linking relationships in the intrusive container. This is what gives this category of containers their name; they are intrusive into the definition of the elements that will be inserted into them. When an element is inserted into an intrusive container, these hooks are set. When it is removed, they are cleared. Intrusive containers thus do not require copying (or moving) elements, nor do they require allocating additional storage for them.
The advantages of an intrusive container are:
noexcept) which would not be possible with a container that needs to allocate storage for elements or copy elements into it.The downsides of intrusive containers are:
In general, the hooks needed for insertion into an intrusive container are added to elements via inheritance; each container type has a base class which elements derive from, and this injects private members into the type. For example, the hook class for arene::base::intrusive::queue is arene::base::intrusive::singly_linked_node.
In addition, these hook classes consume an optional template parameter: Tag, which is a simple tag-type. The Tag is used to allow an element to be inserted into multiple different intrusive containers of the same type at the same time. If Tag is omitted, the default tag is assumed. Similarly, each intrusive container type has an optional Tag template parameter, to specify which elements may be inserted into it. If it is omitted, the default tag is used.
Please see the descriptions of the individual container types below for additional details and examples.
Tag that is used to inject hooks. Only use non-default tags if you are absolutely sure you need them.arene::base::intrusive::queue is a queue data structure: you push elements on the back with arene::base::intrusive::queue::push, pop them off the front via arene::base::intrusive::queue::pop, and the only elements access is to the head an tail of the queue via arene::base::intrusive::queue::front and arene::base::intrusive::queue::back, respectively.
Elements must derive from the hook class arene::base::intrusive::singly_linked_node.
Here, some_data derives from arene::base::intrusive::singly_linked_node in order to provide the necessary fields for linking into the queue. foo then creates 3 instances of the data element, pushes them onto the queue, and then pops them off the queue in a loop.
arene::base::intrusive::priority_queue is a is a max-heap-tree-based intrusive priority queue data structure. It forms a logical priority queue, allowing elements to be added/removed to the priority queue and providing access to the element with the highest priority (depending on the comparator). The default comparator is std::less, but another comparator could be provided to use a different ordering; if comp(a,b) is true then a has lower priority than b.
Elements can be pushed in any order with arene::base::intrusive::priority_queue::push, and popped in priority order with arene::base::intrusive::priority_queue::pop. Also, elements in the queue can be erased (with arene::base::intrusive::priority_queue::erase). Only the "top" element, with the highest priority, can be accessed directly, using arene::base::intrusive::priority_queue::top.
Elements must derive from the hook class arene::base::intrusive::binary_tree_node.
The following example shows elements being removed in priority order, despite being pushed in a different order.
Note that node itself is still valid after being removed with erase, it is just no longer in the queue. Iterators to other elements also remain valid.