/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Copyright 2018 Danny Robson <danny@nerdcruft.net>
 */

#pragma once

#include <atomic>
#include <mutex>
#include <condition_variable>

namespace cruft::thread {
    /// a fire-once event that users can wait upon. if already fired then
    /// waiting will be a noop.
    class flag {
    public:
        flag ();

        /// blocks indefinitely until the flag has been set.
        void wait (void);

        /// wake one thread waiting on the flag.
        ///
        /// it may be possible, through spurious wakeups, that more threads
        /// are release than requested. though this should not be typical.
        void notify_one (void);

        /// wake all threads waiting on the flag
        void notify_all (void);

    private:
        std::atomic<bool> fired;
        std::mutex m_mutex;
        std::condition_variable m_condition;
    };
}