X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=spsc-bugfix%2Feventcount-relacy.h;fp=spsc-bugfix%2Feventcount-relacy.h;h=9eadcf3ab57f78414a7862099c82aea89b3e8975;hb=991d0fdc0fb17f85d485c97dc2c5d8d57a98dad9;hp=0000000000000000000000000000000000000000;hpb=91db0c118d7135f69846bcedfb8a26c0afb44045;p=model-checker-benchmarks.git diff --git a/spsc-bugfix/eventcount-relacy.h b/spsc-bugfix/eventcount-relacy.h new file mode 100644 index 0000000..9eadcf3 --- /dev/null +++ b/spsc-bugfix/eventcount-relacy.h @@ -0,0 +1,64 @@ +class eventcount +{ +public: + eventcount() : waiters(0) + { + count($) = 0; + } + + void signal_relaxed() + { + unsigned cmp = count.load(std::memory_order_relaxed); + signal_impl(cmp); + } + + void signal() + { + unsigned cmp = count.fetch_add(0, std::memory_order_seq_cst); + signal_impl(cmp); + } + + unsigned get() + { + unsigned cmp = count.fetch_or(0x80000000, +std::memory_order_seq_cst); + return cmp & 0x7FFFFFFF; + } + + void wait(unsigned cmp) + { + unsigned ec = count.load(std::memory_order_seq_cst); + if (cmp == (ec & 0x7FFFFFFF)) + { + guard.lock($); + ec = count.load(std::memory_order_seq_cst); + if (cmp == (ec & 0x7FFFFFFF)) + { + waiters($) += 1; + cv.wait(guard, $); + } + guard.unlock($); + } + } + +private: + std::atomic count; + rl::var waiters; + std::mutex guard; + std::condition_variable cv; + + void signal_impl(unsigned cmp) + { + if (cmp & 0x80000000) + { + guard.lock($); + while (false == count.compare_exchange_weak(cmp, + (cmp + 1) & 0x7FFFFFFF, std::memory_order_relaxed)); + unsigned w = waiters($); + waiters($) = 0; + guard.unlock($); + if (w) + cv.notify_all($); + } + } +};