#pragma once #include "gp/vfs/process_data.hpp" #include namespace gp { struct topic_list{ struct node{ std::atomic_bool is_locked; gp::process_data* value; std::atomic next; bool try_acquire() noexcept { bool expected = false; return !(is_locked.compare_exchange_strong(expected, true)); } void release() noexcept { is_locked.store(false); } }; using node_ptr = struct node*; using node_ptr_rep = std::atomic; node_ptr_rep start; node_ptr_rep end; // NODES ARE ACQUIRED ON POP node_ptr try_pop() { auto ptr = start.load(); if(!ptr) return nullptr; if(ptr->try_acquire()) { auto replace = ptr->next.load(); auto expected = ptr; if(end.load() == ptr) { end.store(nullptr); } if(start.compare_exchange_strong(expected, replace)) { return ptr; } else { return nullptr; } } else { return nullptr; } } // ONLY PUSH ACQUIRED NODES, // RELEASE WHEN NO LONGER IN USE bool try_push(node_ptr node) { auto ed = end.load(); if(ed) { if(ed->try_acquire()) { node->next.store(ed); if(end.compare_exchange_strong(ed, node)) { ed->release(); return true; } else { ed->release(); return false; } } else return false; } else { if(end.compare_exchange_strong(ed, node)) { start.store(node); return true; } else { return false; } } } }; }