// Copyright (C) 2003  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#ifndef DLIB_THREADS_KERNEl_1_
#define DLIB_THREADS_KERNEl_1_
#ifdef DLIB_ISO_CPP_ONLY
#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code.  Turn DLIB_ISO_CPP_ONLY off if you want to use it."
#endif
#include "threads_kernel_abstract.h"
#include "../windows_magic.h"
#include <windows.h>
#include "../algs.h"
#include <condition_variable>
#include <mutex>
#include <chrono>
namespace dlib
{
// ----------------------------------------------------------------------------------------
    
    typedef DWORD thread_id_type;
    inline thread_id_type get_thread_id (
    )
    {
        return GetCurrentThreadId();
    }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
    // mutex object
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
    // forward declaration of signaler
    class signaler;
    class mutex
    {
    public:
        mutex (
        ) 
        {
        }
        ~mutex (
        ) {  }
        void lock (
        ) const { cs.lock(); }
        void unlock (
        ) const { cs.unlock(); }
    private:
        friend class signaler;
        mutable std::mutex cs;
        // restricted functions
        mutex(mutex&);        // copy constructor
        mutex& operator=(mutex&);    // assignment operator
    };
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
    // signaler object
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
    class signaler
    {
    public:
        signaler (
            const mutex& associated_mutex
        ) :
            m(associated_mutex)
        {           
        }
        ~signaler (
        ) { }
        void wait (
        ) const
        { 
            std::unique_lock<std::mutex> cs(m.cs, std::defer_lock);
            cv.wait(cs);
        }
        bool wait_or_timeout (
            unsigned long milliseconds
        ) const
        { 
            std::unique_lock<std::mutex> cs(m.cs, std::defer_lock);
            auto status = cv.wait_until(cs, std::chrono::system_clock::now() + std::chrono::milliseconds(milliseconds));
            return status == std::cv_status::no_timeout;
        }
        void signal (
        ) const 
        { 
            cv.notify_one();
        }
        void broadcast (
        ) const 
        { 
            cv.notify_all();
        }
        const mutex& get_mutex (
        ) const { return m; }
    private:
        mutable std::condition_variable cv;
        const mutex& m;
        // restricted functions
        signaler(signaler&);        // copy constructor
        signaler& operator=(signaler&);    // assignment operator
    };
// ----------------------------------------------------------------------------------------
    namespace threads_kernel_shared_helpers
    {
        bool spawn_thread (
            void (*funct)(void*),
            void* param
        );
        /*!
            is identical to create_new_thread() but just doesn't use any thread pooling.
        !*/
    }
// ----------------------------------------------------------------------------------------
}
#include "threads_kernel_shared.h"
#ifdef NO_MAKEFILE
#include "threads_kernel_1.cpp"
#endif
#endif // DLIB_THREADS_KERNEl_1_