Атомно сравнивая - PullRequest
       11

Атомно сравнивая

0 голосов
/ 11 ноября 2018

Я пытаюсь написать реализацию многопоточного режима, ограниченного с обеих сторон стеком, без блокировки.
В операции 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;
};

1 Ответ

0 голосов
/ 12 ноября 2018

Вы ищете атомное сравнение и обмен ?

Вы можете использовать либо atomic_compare_exchange из C11, если он доступен для вашего компилятора, либо искать системно-зависимый и зависимо от компилятора lock cmpxchg встроенный.

Например, для msvc: https://msdn.microsoft.com/en-us/library/ttk2z1ws.aspx

Редактировать: только что нашел это в C ++ 11: std::atomic::compare_exchange_weak / std::atomic::compare_exchange_strong?

...