// Copyright (2019-2022) Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-or-later #ifndef JUNGFRAUJOCH_PARALLEL_STREAM_H #define JUNGFRAUJOCH_PARALLEL_STREAM_H #include #include #include #include #include namespace hls { template class stream { private: mutable std::mutex m; std::condition_variable c_empty; std::condition_variable c_full; std::queue data; std::chrono::seconds timeout; size_t max_elements; void internal_read(T& head) { head = data.front(); data.pop(); c_full.notify_one(); } void internal_write(const T& tail) { data.push(tail); c_empty.notify_one(); } public: explicit stream(size_t nelem = UINT64_MAX, std::chrono::seconds blocking_timeout = std::chrono::minutes(15)) : max_elements(nelem), data(), timeout(blocking_timeout) {}; void write(const T& tail) { std::unique_lock ul(m); while (data.size() >= max_elements) { if (c_full.wait_for(ul, timeout) == std::cv_status::timeout) throw std::runtime_error("Likely deadlock"); } internal_write(tail); } bool write_nb(const T& tail) { std::unique_lock ul(m); if (data.size() >= max_elements) return false; internal_write(tail); return true; } bool read_nb(T& head) { std::unique_lock ul(m); if (data.empty()) return false; internal_read(head); return true; } void read(T& head) { std::unique_lock ul(m); while (data.empty()) { if (c_empty.wait_for(ul, timeout) == std::cv_status::timeout) throw std::runtime_error("Likely deadlock"); } internal_read(head); } bool full() const { std::unique_lock ul(m); return (data.size() >= max_elements); } bool empty() const { std::unique_lock ul(m); return data.empty(); }; size_t size() const { return data.size(); }; void operator >> (T& rval) { read(rval); } void operator << (const T& rval) { write(rval); } T read() { T ret; read(ret); return ret; } }; } #endif //JUNGFRAUJOCH_PARALLEL_STREAM_H