
// dummy

// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation.  William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.

namespace {

#if defined(BOOST_HAS_WINTHREADS)
//:PREVENT THIS FROM BEING DUPLICATED
typedef BOOL (WINAPI* TryEnterCriticalSection_type)(LPCRITICAL_SECTION lpCriticalSection);
TryEnterCriticalSection_type g_TryEnterCriticalSection = 0;
boost::once_flag once_init_TryEnterCriticalSection = BOOST_ONCE_INIT;

void init_TryEnterCriticalSection()
{
    //TryEnterCriticalSection is only available on WinNT 4.0 or later; 
    //it is not available on Win9x.

    OSVERSIONINFO version_info = {sizeof(OSVERSIONINFO)};
    ::GetVersionEx(&version_info);
    if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT && 
        version_info.dwMajorVersion >= 4)
    {
        if (HMODULE kernel_module = GetModuleHandle(TEXT("KERNEL32.DLL")))
            g_TryEnterCriticalSection = reinterpret_cast<TryEnterCriticalSection_type>(GetProcAddress(kernel_module, "TryEnterCriticalSection"));
    }
}

inline bool has_TryEnterCriticalSection()
{
    boost::call_once(init_TryEnterCriticalSection, once_init_TryEnterCriticalSection);
    return g_TryEnterCriticalSection != 0;
}

inline HANDLE mutex_cast(void* p)
{
    return reinterpret_cast<HANDLE>(p);
}

inline LPCRITICAL_SECTION critical_section_cast(void* p)
{
    return reinterpret_cast<LPCRITICAL_SECTION>(p);
}

inline void* new_critical_section()
{
    try
    {
        LPCRITICAL_SECTION critical_section = new ::CRITICAL_SECTION;
        if (critical_section == 0) throw boost::thread_resource_error();
        InitializeCriticalSection(critical_section);
        return critical_section;
    }
    catch(...)
    {
        throw boost::thread_resource_error();
    }
}

inline void* new_mutex(const char* name)
{
#if defined(BOOST_NO_ANSI_APIS)
    USES_CONVERSION;
    HANDLE mutex = CreateMutexW(0, 0, A2CW(name));
#else
    HANDLE mutex = CreateMutexA(0, 0, name);
#endif
    if (mutex == 0 || mutex == INVALID_HANDLE_VALUE) //:xxx (check for both values?)
        throw boost::thread_resource_error();
    return reinterpret_cast<void*>(mutex);
}

inline void delete_critical_section(void* mutex)
{
    DeleteCriticalSection(critical_section_cast(mutex));
    delete critical_section_cast(mutex);
}

inline void delete_mutex(void* mutex)
{
    int res = 0;
    res = CloseHandle(mutex_cast(mutex));
    assert(res);
}

inline void wait_critical_section_infinite(void* mutex)
{
    EnterCriticalSection(critical_section_cast(mutex)); //:xxx Can throw an exception under low memory conditions
}

inline bool wait_critical_section_try(void* mutex)
{
    BOOL res = g_TryEnterCriticalSection(critical_section_cast(mutex));
    return res != 0;
}

inline int wait_mutex(void* mutex, int time)
{
    unsigned int res = 0;
    res = WaitForSingleObject(mutex_cast(mutex), time);
//:xxx    assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
    return res;
}

inline void release_critical_section(void* mutex)
{
    LeaveCriticalSection(critical_section_cast(mutex));
}

inline void release_mutex(void* mutex)
{
    BOOL res = FALSE;
    res = ReleaseMutex(mutex_cast(mutex));
    assert(res);
}
#endif

}
