util/IntrusiveList: add option zero_initialized

This commit is contained in:
Max Kellermann 2023-09-11 19:20:11 +02:00
parent f01793ad4a
commit 7065425927

View File

@ -15,6 +15,14 @@
struct IntrusiveListOptions { struct IntrusiveListOptions {
bool constant_time_size = false; bool constant_time_size = false;
/**
* Initialize the list head with nullptr (all zeroes) which
* adds some code for checking nullptr, but may reduce the
* data section for statically allocated lists. It's a
* trade-off.
*/
bool zero_initialized = false;
}; };
struct IntrusiveListNode { struct IntrusiveListNode {
@ -143,7 +151,9 @@ template<typename T,
class IntrusiveList { class IntrusiveList {
static constexpr bool constant_time_size = options.constant_time_size; static constexpr bool constant_time_size = options.constant_time_size;
IntrusiveListNode head{&head, &head}; IntrusiveListNode head = options.zero_initialized
? IntrusiveListNode{nullptr, nullptr}
: IntrusiveListNode{&head, &head};
[[no_unique_address]] [[no_unique_address]]
OptionalCounter<constant_time_size> counter; OptionalCounter<constant_time_size> counter;
@ -240,6 +250,10 @@ public:
} }
constexpr bool empty() const noexcept { constexpr bool empty() const noexcept {
if constexpr (options.zero_initialized)
if (head.next == nullptr)
return true;
return head.next == &head; return head.next == &head;
} }
@ -383,6 +397,10 @@ public:
}; };
constexpr iterator begin() noexcept { constexpr iterator begin() noexcept {
if constexpr (options.zero_initialized)
if (head.next == nullptr)
return end();
return {head.next}; return {head.next};
} }
@ -454,6 +472,10 @@ public:
}; };
constexpr const_iterator begin() const noexcept { constexpr const_iterator begin() const noexcept {
if constexpr (options.zero_initialized)
if (head.next == nullptr)
return end();
return {head.next}; return {head.next};
} }
@ -498,6 +520,10 @@ public:
GetHookMode() < IntrusiveHookMode::AUTO_UNLINK, GetHookMode() < IntrusiveHookMode::AUTO_UNLINK,
"Can't use auto-unlink hooks with constant_time_size"); "Can't use auto-unlink hooks with constant_time_size");
if constexpr (options.zero_initialized)
if (head.next == nullptr)
head = {&head, &head};
auto &existing_node = *p.cursor; auto &existing_node = *p.cursor;
auto &new_node = ToNode(t); auto &new_node = ToNode(t);
@ -535,6 +561,10 @@ public:
if (_begin == _end) if (_begin == _end)
return; return;
if constexpr (options.zero_initialized)
if (head.next == nullptr)
head = {&head, &head};
auto &next_node = *position.cursor; auto &next_node = *position.cursor;
auto &prev_node = *std::prev(position).cursor; auto &prev_node = *std::prev(position).cursor;