void push(stored_ptr &&new_data) { counted_node_ptr new_next{ 1, allocate_node() }; counted_node_ptr old_tail = tail.load(); for (;;) { increase_external_count(tail, old_tail); T* old_data = nullptr; if (old_tail.get()->data.compare_exchange_strong(old_data, new_data.get())) { counted_node_ptr old_next = { 0, nullptr }; if (!old_tail.get()->next.compare_exchange_strong(old_next, new_next)) { deallocate_node(new_next.get()); new_next = old_next; } set_new_tail(old_tail, new_next); new_data.release(); break; } else { counted_node_ptr old_next = { 0, nullptr }; if (old_tail.get()->next.compare_exchange_strong(old_next, new_next)) { old_next = new_next; new_next.set(allocate_node()); } set_new_tail(old_tail, old_next); } } }
void set_new_tail(counted_node_ptr &old_tail, counted_node_ptr const &new_tail) { node * const current_tail_ptr = old_tail.get(); while (!tail.compare_exchange_weak(old_tail, new_tail) && old_tail.get() == current_tail_ptr) {} if (old_tail.get() == current_tail_ptr) { free_external_counter(old_tail); return; } if (!current_tail_ptr->release_ref()) deallocate_node(current_tail_ptr); }
////Filter2//// //Function to create a tree which has a node with the duplicate file names to the right pointer and non duplicate filenames to the down pointer struct same_size* filter2(struct file_node *head) { struct same_size *h2=NULL,*td=NULL,*tr=NULL,*nod=NULL; struct file_node *temp,*prev; int flag=0; while(head!=NULL) { temp=head; prev=head; flag=1; while(temp->next!=NULL && head->size==temp->next->size) { if(head->inode_no != temp->next->inode_no && compare(head->name,temp->next->name)) { if(flag==1) { nod=(struct same_size*)calloc(1,sizeof(struct same_size)); nod->f_node=*head; if(h2==NULL) { h2=nod; td=h2; tr=h2; } else { td->down=nod; td=td->down; tr=td; } flag=0; } nod=(struct same_size*)calloc(1,sizeof(struct same_size)); nod->f_node=*(temp->next); tr->right=nod; tr=tr->right; deallocate_node(&temp); } else temp=temp->next; } head=head->next; free(prev); } return h2; }
void free_external_counter(counted_node_ptr &old_node_ptr) { node * const ptr = old_node_ptr.get(); int count_increase = old_node_ptr.get_counter() - 2; node_counter old_counter = ptr->count.load(std::memory_order_relaxed); node_counter new_counter; do { new_counter = old_counter; --new_counter.external_counters; new_counter.internal_count += count_increase; } while (!ptr->count.compare_exchange_strong(old_counter, new_counter, std::memory_order_acquire, std::memory_order_relaxed)); if (!new_counter.internal_count && !new_counter.external_counters) deallocate_node(ptr); }
stored_ptr pop() { counted_node_ptr old_head = head.load(std::memory_order_relaxed); for (;;) { increase_external_count(head, old_head); node * const ptr = old_head.get(); if (ptr == tail.load().get()) return nullptr; counted_node_ptr next = ptr->next.load(); if (head.compare_exchange_strong(old_head, next)) { T * const res = ptr->data.exchange(nullptr); free_external_counter(old_head); return stored_ptr(res); } if (!ptr->release_ref()) deallocate_node(ptr); } }
~concurrent_queue() { while (pop() != nullptr) {} deallocate_node(head.load().get()); }