15template <
typename M,
typename T>
16constexpr ptrdiff_t offset_of(M T::*member)
noexcept {
17 constexpr T *dummy =
nullptr;
18 return reinterpret_cast<ptrdiff_t
>(&(dummy->*member));
21template <
typename M,
typename T>
22T *container_of(M T::*member, M *ptr)
noexcept {
23 auto offset = offset_of(member);
25 return reinterpret_cast<T *
>(
reinterpret_cast<uintptr_t
>(ptr) - offset);
28struct SingleLinkEntry {
29 SingleLinkEntry *next =
nullptr;
32struct DoubleLinkEntry {
33 DoubleLinkEntry *next =
nullptr;
34 DoubleLinkEntry *prev =
nullptr;
37class SingleLinkListImpl {
39 SingleLinkListImpl() =
default;
40 SingleLinkListImpl(SingleLinkListImpl &&other) noexcept
41 : head_(std::exchange(other.head_,
nullptr)),
42 tail_(std::exchange(other.tail_,
nullptr)) {}
43 SingleLinkListImpl &operator=(SingleLinkListImpl &&other)
noexcept {
46 head_ = std::exchange(other.head_,
nullptr);
47 tail_ = std::exchange(other.tail_,
nullptr);
52 CONDY_DELETE_COPY(SingleLinkListImpl);
54 void push_back(SingleLinkEntry *entry)
noexcept {
55 assert(entry !=
nullptr);
56 assert(entry->next ==
nullptr);
66 void push_back(SingleLinkListImpl &other)
noexcept {
74 tail_->next = other.head_;
77 other.head_ =
nullptr;
78 other.tail_ =
nullptr;
81 bool empty() const noexcept {
return head_ ==
nullptr; }
83 SingleLinkEntry *pop_front() noexcept {
87 SingleLinkEntry *entry = head_;
92 entry->next =
nullptr;
97 SingleLinkEntry *head_ =
nullptr;
98 SingleLinkEntry *tail_ =
nullptr;
101class DoubleLinkListImpl {
103 DoubleLinkListImpl() =
default;
104 DoubleLinkListImpl(DoubleLinkListImpl &&other) noexcept
105 : head_(std::exchange(other.head_,
nullptr)),
106 tail_(std::exchange(other.tail_,
nullptr)) {}
107 DoubleLinkListImpl &operator=(DoubleLinkListImpl &&other)
noexcept {
108 if (
this != &other) {
110 head_ = std::exchange(other.head_,
nullptr);
111 tail_ = std::exchange(other.tail_,
nullptr);
116 CONDY_DELETE_COPY(DoubleLinkListImpl);
118 void push_back(DoubleLinkEntry *entry)
noexcept {
119 assert(entry !=
nullptr);
120 assert(entry->next ==
nullptr && entry->prev ==
nullptr);
121 entry->next =
nullptr;
132 bool empty() const noexcept {
return head_ ==
nullptr; }
134 DoubleLinkEntry *pop_front() noexcept {
138 DoubleLinkEntry *entry = head_;
141 head_->prev =
nullptr;
145 entry->next =
nullptr;
146 entry->prev =
nullptr;
150 bool remove(DoubleLinkEntry *entry)
noexcept {
151 assert(entry !=
nullptr);
152 if (entry->prev ==
nullptr && entry->next ==
nullptr &&
157 entry->prev->next = entry->next;
159 assert(head_ == entry);
163 entry->next->prev = entry->prev;
165 assert(tail_ == entry);
168 entry->next =
nullptr;
169 entry->prev =
nullptr;
174 DoubleLinkEntry *head_ =
nullptr;
175 DoubleLinkEntry *tail_ =
nullptr;
178template <
typename T, SingleLinkEntry T::*Member>
class IntrusiveSingleList {
180 void push_back(T *item)
noexcept { impl_.push_back(&(item->*Member)); }
182 void push_back(IntrusiveSingleList other)
noexcept {
183 impl_.push_back(other.impl_);
186 bool empty() const noexcept {
return impl_.empty(); }
188 T *pop_front() noexcept {
189 SingleLinkEntry *entry = impl_.pop_front();
190 return entry ? container_of(Member, entry) : nullptr;
194 SingleLinkListImpl impl_;
197template <
typename T, DoubleLinkEntry T::*Member>
class IntrusiveDoubleList {
199 void push_back(T *item)
noexcept { impl_.push_back(&(item->*Member)); }
201 bool empty() const noexcept {
return impl_.empty(); }
203 T *pop_front() noexcept {
204 DoubleLinkEntry *entry = impl_.pop_front();
205 return entry ? container_of(Member, entry) : nullptr;
208 bool remove(T *item)
noexcept {
return impl_.remove(&(item->*Member)); }
211 DoubleLinkListImpl impl_;
The main namespace for the Condy library.
Internal utility classes and functions used by Condy.