|
| 1 | +#include <atomic> |
| 2 | +#include <condition_variable> |
| 3 | +#include <cstring> |
| 4 | +#include <mutex> |
| 5 | + |
| 6 | +#include "../specs/buffered_channel.h" |
| 7 | +#include "runtime/include/verifying.h" |
| 8 | +#include "verifiers/buffered_channel_verifier.h" |
| 9 | + |
| 10 | +struct BufferedChannel { |
| 11 | + non_atomic void Send(int v) { |
| 12 | + std::unique_lock lock{mutex_}; |
| 13 | + while (!closed_ && full_) { |
| 14 | + debug(stderr, "Waiting in send...\n"); |
| 15 | + send_side_cv_.wait(lock); |
| 16 | + } |
| 17 | + debug(stderr, "Send\n"); |
| 18 | + |
| 19 | + queue_[sidx_] = v; |
| 20 | + sidx_ = (sidx_ + 1) % N; |
| 21 | + empty_ = false; |
| 22 | + recv_side_cv_.notify_one(); |
| 23 | + } |
| 24 | + |
| 25 | + non_atomic int Recv() { |
| 26 | + std::unique_lock lock{mutex_}; |
| 27 | + while (!closed_ && empty_) { |
| 28 | + debug(stderr, "Waiting in recv...\n"); |
| 29 | + recv_side_cv_.wait(lock); |
| 30 | + } |
| 31 | + debug(stderr, "Recv\n"); |
| 32 | + auto val = queue_[ridx_]; |
| 33 | + ridx_ = (ridx_ + 1) % N; |
| 34 | + empty_ = (sidx_ == ridx_); |
| 35 | + full_ = false; |
| 36 | + send_side_cv_.notify_one(); |
| 37 | + return val; |
| 38 | + } |
| 39 | + |
| 40 | + void Close() { |
| 41 | + closed_.store(true); |
| 42 | + send_side_cv_.notify_all(); |
| 43 | + recv_side_cv_.notify_all(); |
| 44 | + } |
| 45 | + |
| 46 | + std::mutex mutex_; |
| 47 | + std::condition_variable send_side_cv_, recv_side_cv_; |
| 48 | + std::atomic<bool> closed_{false}; |
| 49 | + |
| 50 | + bool full_{false}; |
| 51 | + bool empty_{true}; |
| 52 | + |
| 53 | + uint32_t sidx_{0}, ridx_{0}; |
| 54 | + |
| 55 | + std::array<int, N> queue_{}; |
| 56 | +}; |
| 57 | + |
| 58 | +auto generateInt(size_t) { |
| 59 | + return ltest::generators::makeSingleArg(rand() % 10 + 1); |
| 60 | +} |
| 61 | + |
| 62 | +using spec_t = |
| 63 | + ltest::Spec<BufferedChannel, spec::BufferedChannel, |
| 64 | + spec::BufferedChannelHash, spec::BufferedChannelEquals>; |
| 65 | + |
| 66 | +LTEST_ENTRYPOINT_CONSTRAINT(spec_t, spec::BufferedChannelVerifier); |
| 67 | + |
| 68 | +target_method(generateInt, void, BufferedChannel, Send, int); |
| 69 | +target_method(ltest::generators::genEmpty, int, BufferedChannel, Recv); |
0 commit comments