// // Created by loki on 6/10/19. // #ifndef SUNSHINE_THREAD_SAFE_H #define SUNSHINE_THREAD_SAFE_H #include #include #include #include "utility.h" namespace safe { template class event_t { using status_t = util::optional_t; public: template void raise(Args &&...args) { std::lock_guard lg { _lock }; if(!_continue) { return; } _status = status_t { std::forward(args)... }; _cv.notify_all(); } status_t pop() { std::unique_lock ul{_lock}; if (!_continue) { return util::false_v; } while (!_status) { _cv.wait(ul); if (!_continue) { return util::false_v; } } auto val = std::move(_status); _status = util::false_v; return val; } bool peek() { std::lock_guard lg { _lock }; return (bool)_status; } void stop() { std::lock_guard lg{_lock}; _continue = false; _cv.notify_all(); } bool running() const { return _continue; } private: bool _continue{true}; status_t _status; std::condition_variable _cv; std::mutex _lock; }; template class queue_t { using status_t = util::optional_t; public: template void raise(Args &&... args) { std::lock_guard lg{_lock}; if(!_continue) { return; } _queue.emplace_back(std::forward(args)...); _cv.notify_all(); } bool peek() { std::lock_guard lg { _lock }; return !_queue.empty(); } status_t pop() { std::unique_lock ul{_lock}; if (!_continue) { return util::false_v; } while (_queue.empty()) { _cv.wait(ul); if (!_continue) { return util::false_v; } } auto val = std::move(_queue.front()); _queue.erase(std::begin(_queue)); return val; } std::vector &unsafe() { return _queue; } void stop() { std::lock_guard lg{_lock}; _continue = false; _cv.notify_all(); } bool running() const { return _continue; } private: bool _continue{true}; std::mutex _lock; std::condition_variable _cv; std::vector _queue; }; } #endif //SUNSHINE_THREAD_SAFE_H