/*
 * 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 "../win32/handle.hpp"

#include <atomic>


namespace cruft::thread {
    /// Explicitly does not conform to BasicLockable.
    class semaphore {
    public:
        using value_type = LONG;

        semaphore (value_type initial);
        semaphore ();

        semaphore (const semaphore&) = delete;
        semaphore& operator= (const semaphore&) = delete;
        semaphore (semaphore&&) = delete;
        semaphore& operator= (semaphore&&) = delete;

        value_type acquire (void);
        value_type acquire (value_type count);
        value_type release (void);
        value_type release (value_type count);

        auto   lock (void) { return acquire (); }
        auto unlock (void) { return release (); }

        value_type value (void) const;

        value_type operator++ (void);
        value_type operator-- (void);

    private:
        std::atomic<LONG> m_value;
        ::cruft::win32::handle m_handle;
    };
};