2019-12-24 15:05:24 +00:00
|
|
|
#ifndef cwMpScNbQueue_h
|
|
|
|
#define cwMpScNbQueue_h
|
|
|
|
|
|
|
|
namespace cw
|
|
|
|
{
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
class MpScNbQueue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct node_str
|
|
|
|
{
|
|
|
|
std::atomic<struct node_str*> next = nullptr;
|
|
|
|
T* payload = nullptr;
|
|
|
|
} node_t;
|
|
|
|
|
|
|
|
MpScNbQueue()
|
|
|
|
{
|
2019-12-28 02:51:28 +00:00
|
|
|
node_t* stub = mem::allocZ<node_t>();
|
2019-12-24 15:05:24 +00:00
|
|
|
_head = stub;
|
|
|
|
_tail = stub;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~MpScNbQueue()
|
2019-12-28 02:51:28 +00:00
|
|
|
{ mem::free(_tail); }
|
2019-12-24 15:05:24 +00:00
|
|
|
|
|
|
|
MpScNbQueue( const MpScNbQueue& ) = delete;
|
|
|
|
MpScNbQueue( const MpScNbQueue&& ) = delete;
|
|
|
|
MpScNbQueue& operator=(const MpScNbQueue& ) = delete;
|
|
|
|
MpScNbQueue& operator=(const MpScNbQueue&& ) = delete;
|
|
|
|
|
|
|
|
|
|
|
|
void push( T* payload )
|
|
|
|
{
|
2019-12-28 02:51:28 +00:00
|
|
|
node_t* new_node = mem::allocZ<node_t>(1);
|
2019-12-24 15:05:24 +00:00
|
|
|
new_node->payload = payload;
|
|
|
|
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)
|
|
|
|
prev->next.store(new_node,std::memory_order_release); // make the new node accessible by the consumer (release to consumer)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
T* pop()
|
|
|
|
{
|
|
|
|
T* payload = nullptr;
|
|
|
|
node_t* t = _tail;
|
|
|
|
node_t* next = t->next.load(std::memory_order_acquire); // acquire from producer
|
|
|
|
if( next != nullptr )
|
|
|
|
{
|
|
|
|
_tail = next;
|
|
|
|
payload = next->payload;
|
2019-12-28 02:51:28 +00:00
|
|
|
mem::free(t);
|
2019-12-24 15:05:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return payload;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isempty() const
|
|
|
|
{
|
|
|
|
return _tail->next.load(std::memory_order_acquire) == nullptr; // acquire from producer
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
void _push( node_t* new_node )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
node_t* _stub;
|
|
|
|
node_t* _tail;
|
|
|
|
std::atomic<node_t*> _head;
|
|
|
|
};
|
|
|
|
|
|
|
|
void mpScNbQueueTest();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|