#pragma once

#include <condition_variable>

#include "Betriebssystem.h"

namespace Framework
{
    class Thread;

    class Critical
    {
    private:
        CRITICAL_SECTION cs;
        Thread* owner;
        int lockCount;
        int id;

    public:
        //! Konstructor
        DLLEXPORT Critical();
        //! Destructor
        DLLEXPORT ~Critical();
        //! sperrt das Objekt
        DLLEXPORT void lock();
        //! versucht das Objekt zu sperren
        DLLEXPORT bool tryLock();
        //! entsperrt das Objekt
        DLLEXPORT void unlock();

        //! gibt true zurück, wenn das Objekt gesperrt ist
        DLLEXPORT bool isLocked() const;
        //! gibt einen Zeiger auf den Thread zurück, der das Objekt gesperrt hat
        DLLEXPORT const Thread* zOwner() const;
    };

    class Synchronizer
    {
    private:
        std::condition_variable block;
        std::mutex mutex;
        int numWaiting;
        bool skip;

    public:
        DLLEXPORT Synchronizer();
        DLLEXPORT ~Synchronizer();

        DLLEXPORT bool wait();
        DLLEXPORT bool wait(int milisec);
        DLLEXPORT void notify();
        DLLEXPORT void notify(int amount);
        DLLEXPORT void notifyAll();

        DLLEXPORT int getNumberOfWaitingThreads() const;
    };
} // namespace Framework