Я пытаюсь написать реализацию многопоточного режима, ограниченного с обеих сторон стеком, без блокировки.
В операции push
мне нужно сравнить size
с capacity
и, если они не равны, установить новый элемент head для стека.
Каков верный способ сделать это?
Если я напишу
if (size == cap) {
return;
}
// append element
Я не буду уверен, тогда другой поток не вставит последнее значение в стек сразу после сравнения.
#include <atomic>
#include <boost/next_prior.hpp>
#include <boost/lockfree/spsc_queue.hpp>
#include <boost/function.hpp>
template<typename T>
struct Node
{
Node(const T& data)
:data(data), next(nullptr) {}
public:
T data;
Node* next;
};
template <typename T>
class Stack {
using WriteCallback = typename std::function<void (const T&)>;
using ReadCallback = typename std::function<void (T&&)>;
template<typename T1>
using queue = boost::lockfree::spsc_queue<T1>;
public:
Stack(int cap)
:head(nullptr),
size(0),
cap(cap),
onWrite(0),
onRead(0)
{}
void push(const T& val, WriteCallback cb)
{
if (size == cap) {
onWrite.push(cb);
return;
}
// insertion will be here
}
private:
Node* head;
std::atomic<int> size;
std::atomic<int> cap;
queue<WriteCallback> onWrite;
queue<ReadCallback> onRead;
};