60 struct counted_node_ptr {
61 int external_count = 0;
67 counted_node_ptr()
noexcept {}
85 explicit node(
int external_count = 2) {
86 node_counter new_count;
87 new_count.internal_count = 0;
88 new_count.external_counters = external_count;
89 count.store(new_count);
91 counted_node_ptr node_ptr;
92 node_ptr.ptr =
nullptr;
93 node_ptr.external_count = 0;
105 node_counter new_counter;
107 new_counter = old_counter;
108 --new_counter.internal_count;
111 if (!new_counter.internal_count && !new_counter.external_counters) {
113 destruct_count.fetch_add(1);
135 void set_new_tail(counted_node_ptr& old_tail, counted_node_ptr
const& new_tail) {
136 node*
const current_tail_ptr = old_tail.ptr;
137 while (!tail.compare_exchange_weak(old_tail, new_tail) && old_tail.ptr == current_tail_ptr) {
138 this_thread::relax();
140 if (old_tail.ptr == current_tail_ptr) {
141 lock_free_queue::free_external_counter(old_tail);
143 current_tail_ptr->release_ref();
154 static void free_external_counter(counted_node_ptr& old_node_ptr) {
155 node*
const ptr = old_node_ptr.ptr;
156 int const count_increase = old_node_ptr.external_count - 2;
158 node_counter new_counter;
160 new_counter = old_counter;
161 --new_counter.external_counters;
162 new_counter.internal_count += count_increase;
165 if (!new_counter.internal_count && !new_counter.external_counters) {
166 destruct_count.fetch_add(1);
180 counted_node_ptr new_counter;
182 new_counter = old_counter;
183 ++new_counter.external_count;
186 old_counter.external_count = new_counter.external_count;
196 counted_node_ptr new_next;
197 new_next.ptr =
new node();
198 new_next.external_count = 1;
199 tail.store(new_next);
200 head.store(new_next);
210 this_thread::relax();
212 auto head_counted_node = head.load();
213 delete head_counted_node.ptr;
225 counted_node_ptr new_next;
226 new_next.ptr =
new node;
227 new_next.external_count = 1;
228 counted_node_ptr old_tail = tail.load();
230 lock_free_queue::increase_external_count(tail, old_tail);
231 T* old_data =
nullptr;
233 counted_node_ptr old_next;
234 counted_node_ptr now_next = old_tail.ptr->next.
load();
239 this->set_new_tail(old_tail, new_next);
243 counted_node_ptr old_next;
246 new_next.ptr =
new node;
248 this->set_new_tail(old_tail, old_next);
264 lock_free_queue::increase_external_count(head, old_head);
265 node*
const ptr = old_head.ptr;
266 if (ptr == tail.load().ptr) {
270 counted_node_ptr
next = ptr->next.
load();
271 if (head.compare_exchange_strong(old_head,
next)) {
272 T* res = ptr->data.
exchange(
nullptr);
273 lock_free_queue::free_external_counter(old_head);
291 counted_node_ptr old_head{};
295 lock_free_queue::increase_external_count(head, old_head);
296 node* ptr = old_head.ptr;
298 if (ptr == tail.load().ptr) {
303 counted_node_ptr
next = ptr->next.
load();
304 if (head.compare_exchange_strong(old_head,
next)) {
305 T* res = ptr->data.
exchange(
nullptr);
306 lock_free_queue::free_external_counter(old_head);
327 return head_ptr.ptr == tail_ptr.ptr;
341 return push_cnt - pop_cnt;
357 this_thread::relax();