|  | #pragma once | 
					
						
						|  |  | 
					
						
						|  | #include <utility> | 
					
						
						|  | #include <string> | 
					
						
						|  | #include <mutex> | 
					
						
						|  | #include <atomic> | 
					
						
						|  |  | 
					
						
						|  | #include "libipc/def.h" | 
					
						
						|  | #include "libipc/mutex.h" | 
					
						
						|  | #include "libipc/condition.h" | 
					
						
						|  | #include "libipc/platform/detail.h" | 
					
						
						|  |  | 
					
						
						|  | namespace ipc { | 
					
						
						|  | namespace detail { | 
					
						
						|  |  | 
					
						
						|  | class waiter { | 
					
						
						|  | ipc::sync::condition cond_; | 
					
						
						|  | ipc::sync::mutex     lock_; | 
					
						
						|  | std::atomic<bool>    quit_ {false}; | 
					
						
						|  |  | 
					
						
						|  | public: | 
					
						
						|  | static void init(); | 
					
						
						|  |  | 
					
						
						|  | waiter() = default; | 
					
						
						|  | waiter(char const *name) { | 
					
						
						|  | open(name); | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | ~waiter() { | 
					
						
						|  | close(); | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | bool valid() const noexcept { | 
					
						
						|  | return cond_.valid() && lock_.valid(); | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | bool open(char const *name) noexcept { | 
					
						
						|  | quit_.store(false, std::memory_order_relaxed); | 
					
						
						|  | if (!cond_.open((std::string{"_waiter_cond_"} + name).c_str())) { | 
					
						
						|  | return false; | 
					
						
						|  | } | 
					
						
						|  | if (!lock_.open((std::string{"_waiter_lock_"} + name).c_str())) { | 
					
						
						|  | cond_.close(); | 
					
						
						|  | return false; | 
					
						
						|  | } | 
					
						
						|  | return valid(); | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | void close() noexcept { | 
					
						
						|  | cond_.close(); | 
					
						
						|  | lock_.close(); | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | template <typename F> | 
					
						
						|  | bool wait_if(F &&pred, std::uint64_t tm = ipc::invalid_value) noexcept { | 
					
						
						|  | IPC_UNUSED_ std::lock_guard<ipc::sync::mutex> guard {lock_}; | 
					
						
						|  | while ([this, &pred] { | 
					
						
						|  | return !quit_.load(std::memory_order_relaxed) | 
					
						
						|  | && std::forward<F>(pred)(); | 
					
						
						|  | }()) { | 
					
						
						|  | if (!cond_.wait(lock_, tm)) return false; | 
					
						
						|  | } | 
					
						
						|  | return true; | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | bool notify() noexcept { | 
					
						
						|  | std::lock_guard<ipc::sync::mutex>{lock_}; | 
					
						
						|  | return cond_.notify(lock_); | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | bool broadcast() noexcept { | 
					
						
						|  | std::lock_guard<ipc::sync::mutex>{lock_}; | 
					
						
						|  | return cond_.broadcast(lock_); | 
					
						
						|  | } | 
					
						
						|  |  | 
					
						
						|  | bool quit_waiting() { | 
					
						
						|  | quit_.store(true, std::memory_order_release); | 
					
						
						|  | return broadcast(); | 
					
						
						|  | } | 
					
						
						|  | }; | 
					
						
						|  |  | 
					
						
						|  | } | 
					
						
						|  | } | 
					
						
						|  |  |