Skip to content

Commit

Permalink
[free_list] documentation pass for free_list
Browse files Browse the repository at this point in the history
  • Loading branch information
harrand committed Jan 16, 2024
1 parent dc092db commit abc2710
Showing 1 changed file with 71 additions and 0 deletions.
71 changes: 71 additions & 0 deletions src/tz/core/data/free_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@ namespace tz
}


/**
* @ingroup tz_core_data
* Bespoke free-list implementation. Container adaptor that deals with stable, opaque handles to nullable elements. Erased elements are represented by the `null` value. Erased elements are re-cycled in subsequent new elements.
* - No pointer stability.
* - Random access.
* - Index stability (via opaque handles).
* - No agency over orderedness.
* - push_back and emplace_back may re-use old slots instead of actually adding to the end of the list.
*/
template<tz::nullable T, tz::random_access_container C>
class free_list
{
Expand All @@ -116,6 +125,7 @@ namespace tz
using const_iterator = free_list_iterator<T, C, const free_list<T, C>>;
friend struct free_list_iterator<T, C, free_list<T, C>>;
friend struct free_list_iterator<T, C, const free_list<T, C>>;
/// Create an empty free list.
free_list() = default;
free_list(const free_list<T, C>& cpy) = default;
free_list(free_list<T, C>&& move) = default;
Expand All @@ -124,34 +134,95 @@ namespace tz
free_list& operator=(free_list<T, C>&& rhs);
free_list& operator=(C&& container);

/// Retrieve the number of elements.
std::size_t size() const;
/// Query as to whether the list is empty. Equivalent to `size() == 0`.
bool empty() const;
/// Remove all elements, and clear out the underlying free-list. Next handle returned is guaranteed to be 0. Invalidates all references and iterators.
void clear();
/// Invoke `reserve(count)` on the underlying container. Does not invalidate iterators. Only invalidates references if the underlying container's `reserve` method also does so.
void reserve(std::size_t count);

iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;

/**
* Add a copy of a new element to the list.
* - Invalidates iterators and references.
* @note `push_back` is a poor name for this function. If an element has previously been erased, its location in the list may be re-used for this new element, instead of adding the element at the end.
* O(x) where `x` is the worst-case time complexity of the underlying container's `emplace_back` method.
* θ(1)
*/
handle push_back(const T& t) requires
requires(C con, T t) {con.push_back(t);};

/**
* Move a new element into the list.
* - Invalidates iterators and references.
* @note `push_back` is a poor name for this function. If an element has previously been erased, its location in the list may be re-used for this new element, instead of adding the element at the end.
* O(x) where `x` is the worst-case time complexity of the underlying container's `emplace_back` method.
* θ(1)
*/
handle push_back(T&& t) requires
requires(C con, T&& t) {con.push_back(std::move(t));};

/**
* Construct a new element in-place within the list.
* - Invalidates iterators and references.
* @note `emplace_back` is a poor name for this function. If an element has previously been erased, its location in the list may be re-used for this new element, instead of adding the element at the end.
* O(x) where `x` is the worst-case time complexity of the underlying container's `emplace_back` method.
* θ(1)
*/
template<typename... Ts>
handle emplace_back(Ts&&... ts) requires
requires(C con) {{con.emplace_back(std::forward<Ts>(ts)...)} -> std::same_as<T&>;};

/**
* Erase an existing element from the list using its handle.
* - Invalidates iterators, but does not invalidate references.
* O(m), where `m` is the number of previously-freed elements that have not yet been recycled. Unaffected by `size()` of the free list.
* θ(1)
*/
void erase(handle h);

/**
* Retrieve the first non-null element within the list.
* O(m), where `m` is the number of previously-freed elements that have not yet been recycled.
* θ(1)
*/
const T& front() const;
/**
* Retrieve the first non-null element within the list.
* O(m), where `m` is the number of previously-freed elements that have not yet been recycled.
* θ(1)
*/
T& front();
/**
* Retrieve the last non-null element within the list.
* O(m), where `m` is the number of previously-freed elements that have not yet been recycled.
* θ(1)
*/
const T& back() const;
/**
* Retrieve the last non-null element within the list.
* O(m), where `m` is the number of previously-freed elements that have not yet been recycled.
* θ(1)
*/
T& back();

/**
* Retrieve the element value corresponding to the provided handle.
* O(x) where `x` is the worst-case time complexity of the underlying container's `operator[]` method.
* θ(x) where `x` is the worst-case time complexity of the underlying container's `operator[]` method.
*/
const T& operator[](handle h) const;
/**
* Retrieve the element value corresponding to the provided handle.
* O(x) where `x` is the worst-case time complexity of the underlying container's `operator[]` method.
* θ(x) where `x` is the worst-case time complexity of the underlying container's `operator[]` method.
*/
T& operator[](handle h);
private:
bool is_in_free_list(std::size_t internal_id) const;
Expand Down

0 comments on commit abc2710

Please sign in to comment.