cwMpScNbQueue.h : Added comments.

This commit is contained in:
kpl 2020-01-27 17:50:02 -05:00
parent 1849edf7cc
commit 46b42b34ef

View File

@ -9,7 +9,6 @@ namespace cw
{ {
public: public:
typedef struct node_str typedef struct node_str
{ {
std::atomic<struct node_str*> next = nullptr; std::atomic<struct node_str*> next = nullptr;
@ -19,8 +18,8 @@ namespace cw
MpScNbQueue() MpScNbQueue()
{ {
node_t* stub = mem::allocZ<node_t>(); node_t* stub = mem::allocZ<node_t>();
_head = stub; _head = stub; // last-in
_tail = stub; _tail = stub; // first-out
} }
virtual ~MpScNbQueue() virtual ~MpScNbQueue()
@ -37,8 +36,18 @@ namespace cw
node_t* new_node = mem::allocZ<node_t>(1); node_t* new_node = mem::allocZ<node_t>(1);
new_node->payload = payload; new_node->payload = payload;
new_node->next.store(nullptr); new_node->next.store(nullptr);
node_t* prev = _head.exchange(new_node,std::memory_order_acq_rel); // append the new node to the list (aquire-release) // Note that the elements of the queue are only accessed from the end of the queue (tail).
prev->next.store(new_node,std::memory_order_release); // make the new node accessible by the consumer (release to consumer) // New nodes can therefore safely be updated in two steps:
// 1. Atomically set _head to the new node and return 'old-head'
node_t* prev = _head.exchange(new_node,std::memory_order_acq_rel);
// Note that at this point only the new node may have the 'old-head' as it's predecssor.
// Other threads may therefore safely interrupt at this point.
// 2. Set the old-head next pointer to the new node (thereby adding the new node to the list)
prev->next.store(new_node,std::memory_order_release); // RELEASE 'next' to consumer
} }
@ -46,7 +55,7 @@ namespace cw
{ {
T* payload = nullptr; T* payload = nullptr;
node_t* t = _tail; node_t* t = _tail;
node_t* next = t->next.load(std::memory_order_acquire); // acquire from producer node_t* next = t->next.load(std::memory_order_acquire); // ACQUIRE 'next' from producer
if( next != nullptr ) if( next != nullptr )
{ {
_tail = next; _tail = next;
@ -60,15 +69,11 @@ namespace cw
bool isempty() const bool isempty() const
{ {
return _tail->next.load(std::memory_order_acquire) == nullptr; // acquire from producer return _tail->next.load(std::memory_order_acquire) == nullptr; // ACQUIRE 'next' from producer
} }
private: private:
void _push( node_t* new_node )
{
}
node_t* _stub; node_t* _stub;
node_t* _tail; node_t* _tail;
std::atomic<node_t*> _head; std::atomic<node_t*> _head;