实现有界缓冲区(读写器之间的非块,读取器之间的块,写入器之间的块)

时间:2016-09-13 21:52:14

标签: c++ multithreading concurrency

实施有界队列

读:
如果队列为空,请等到它可以在超时时返回值 如果另一个线程正在从队列中读取,那么请等待该线程完成 从队列中删除第一个元素并将其返回
如果线程正在写入队列,请不要阻止

写:
如果队列已满,请等待一个值超时读取一个值 如果另一个线程正在写入队列,请等待该线程完成 将元素写在队列的末尾
如果线程正在从队列中读取,请不要阻止

我不确定我的实施是否正确

if

1 个答案:

答案 0 :(得分:0)

在我的代码中发现了一个错误:
在put()和get()方法中,它调用wait_for()并检查返回值 如果它超时,则返回false,否则它假定满足等待条件并且代码继续输入/获取数据。
如果由于虚假唤醒而返回wait_for(),并且当条件未满足时:
不完整的put()而不是空的()get,
然后它会覆盖现有数据或读取错误数据。

修复是在wait_for()中使用谓词。它会忽略虚假的唤醒。

    bool put(const T& data) {
            unique_lock<mutex> writer_lock(writer_mutex);

            {
                    unique_lock<mutex> shared_lock(shared_mutex);
                    if (full()) { //buffer full
                            if (writer_queue.wait_for(shared_lock, std::chrono::milliseconds(timeout),
                                    [this]() { return !full(); }) == false) {
                                    return false;
                            }
                    }
            }

            buffer[write_pos%N] = data;
            write_pos++;
            reader_queue.notify_one();
            return true;
    }


    pair<T, bool> get(int i) {
            unique_lock<mutex> reader_lock(reader_mutex);
            cout << "i : " << i << endl;

            {
                    unique_lock<mutex> shared_lock(shared_mutex);
                    if (empty()) { //buffer empty
                            if (reader_queue.wait_for(shared_lock, std::chrono::milliseconds(timeout),
                                    [this]() { return !empty(); })==false) {
                                    T t;
                                    return make_pair(t, false);
                            }
                    }
            }

            pair<T, bool> result = make_pair(buffer[read_pos%N], true);
            read_pos++;
            writer_queue.notify_one();
            return result;
    }