#ifndef INCLUDED_BOBCAT_SEMAPHORE_
#define INCLUDED_BOBCAT_SEMAPHORE_

#include <mutex>
#include <condition_variable>
#include <chrono>

namespace FBB
{

class Semaphore
{
    mutable std::mutex d_mutex;
    std::condition_variable d_condition;
    size_t d_nAvailable;

    public:
        Semaphore(size_t nAvailable);

        template <typename Fun, typename ...Params>
        bool wait(Fun fun, Params &&...args);        // wait # available

        void wait();        // wait # available
                                        
                            // wait for duration timeunits
        template <typename Rep, typename Period>
        std::cv_status wait_for(std::chrono::duration<Rep, Period> 
                                                            const &relTime);

                            // wait until abs. time has been reached
        template <typename Clock, typename Duration>  
        std::cv_status wait_until(std::chrono::time_point<Clock, Duration> 
                                                            const &absTime);

        void notify();      // notify a single waiting thread if initially 0
        void notify_all();  // notify_all # available, notify if initially 0

        void set(size_t available = 0);
        size_t size() const;
};

#include "size.f"
#include "waitfor.f"
#include "waituntil.f"
#include "waitfun.f"


}   // FBB

#endif
