Skip to content

File stoplight.hpp

File List > illixr > stoplight.hpp

Go to the documentation of this file

#pragma once

#include "phonebook.hpp"

#include 
#include 
#include 

namespace ILLIXR {

class event {
public:
    void set(bool new_value = true) {
        {
            std::lock_guard lock{mutex_};
            value_ = new_value;
        }
        if (new_value) {
            cv_.notify_all();
        }
    }

    void clear() {
        set(false);
    }

    bool is_set() const {
        return value_;
    }

    void wait() const {
        std::unique_lock<std::mutex> lock{mutex_};
        // Check if we even need to wait
        if (value_) {
            return;
        }
        cv_.wait(lock, [this] {
            return value_.load();
        });
    }

    template<class Clock, class Rep, class Period>
    [[maybe_unused]] bool wait_timeout(const std::chrono::duration<Rep, Period>& duration) const {
        auto timeout_time = Clock::now() + duration;
        if (value_) {
            return true;
        }
        std::unique_lock<std::mutex> lock{mutex_};
        while (cv_.wait_until(lock, timeout_time) != std::cv_status::timeout) {
            if (value_) {
                return true;
            }
        }
        return false;
    }

private:
    mutable std::mutex              mutex_;
    mutable std::condition_variable cv_;
    std::atomic<bool>               value_ = false;
};

class stoplight : public phonebook::service {
public:
    void wait_for_ready() const {
        ready_.wait();
    }

    void signal_ready() {
        ready_.set();
    }

    bool check_should_stop() const {
        return should_stop_.is_set();
    }

    void wait_for_should_stop() const {
        should_stop_.wait();
    }

    void signal_should_stop() {
        should_stop_.set();
    }

    void wait_for_shutdown_complete() const {
        shutdown_complete_.wait();
    }

    bool check_shutdown_complete() const {
        return shutdown_complete_.is_set();
    }

    void signal_shutdown_complete() {
        shutdown_complete_.set();
    }

private:
    event ready_;
    event should_stop_;
    event shutdown_complete_;
};

} // namespace ILLIXR