#include "stdafx.h"
#include <process.h>
#include "hwinthread.h"
namespace harlinn
{
namespace windows
{
namespace threading
{
// -----------------------------------------------------------------
// ThreadHandle
// -----------------------------------------------------------------
HWIN_EXPORT HANDLE ThreadHandle::CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,SIZE_T dwStackSize,
ThreadHandle* pThreadHandle,DWORD dwCreationFlags)
{
unsigned threadId;
HANDLE result = (HANDLE)_beginthreadex(lpThreadAttributes,UINT(dwStackSize),ThreadStart,pThreadHandle,dwCreationFlags | CREATE_SUSPENDED,&threadId);
if(result == nullptr)
{
ThrowLastOSError();
}
pThreadHandle->threadId = threadId;
return result;
}
HWIN_EXPORT unsigned __stdcall ThreadHandle::ThreadStart(void* lpThreadParameter)
{
ThreadHandle* pThreadHandle = reinterpret_cast<ThreadHandle*>(lpThreadParameter);
DWORD result = 0;
try
{
std::shared_ptr<ThreadHandle> threadHandle = pThreadHandle->As<ThreadHandle>();
CurrentThreadHandle::currentThreadData->threadHandle = threadHandle;
result = pThreadHandle->DoOnRun();
}
catch(std::exception& exc)
{
}
catch(...)
{
}
_endthreadex(result);
return result;
}
HWIN_EXPORT ThreadHandle::ThreadHandle(DWORD stackSize, bool stackSizeIsReservation)
{
HANDLE h = CreateThread(nullptr,stackSize,this,(stackSizeIsReservation?STACK_SIZE_PARAM_IS_A_RESERVATION:0));
SetValue(h,true);
}
HWIN_EXPORT std::shared_ptr<CurrentThreadHandle> ThreadHandle::Current()
{
auto result = std::make_shared<CurrentThreadHandle>();
return result;
}
HWIN_EXPORT ThreadHandle& ThreadHandle::Start()
{
if(ResumeThread(GetHANDLE()) == ((DWORD)-1))
{
ThrowLastOSError();
}
return *this;
}
HWIN_EXPORT DWORD ThreadHandle::ThreadId() const
{
return threadId;
}
HWIN_EXPORT ThreadHandle::ThreadPriority_t ThreadHandle::ThreadPriority() const
{
int result = GetThreadPriority(GetHANDLE());
if(result == THREAD_PRIORITY_ERROR_RETURN)
{
ThrowLastOSError();
}
return ThreadPriority_t(result);
}
HWIN_EXPORT ThreadHandle& ThreadHandle::SetThreadPriority(ThreadPriority_t theThreadPriority)
{
if(::SetThreadPriority(GetHANDLE(),int(theThreadPriority)) == 0)
{
ThrowLastOSError();
}
return *this;
}
HWIN_EXPORT DWORD ThreadHandle::Suspend()
{
DWORD result = SuspendThread(GetHANDLE());
if(result == (DWORD) -1)
{
ThrowLastOSError();
}
return result;
}
HWIN_EXPORT DWORD ThreadHandle::Resume()
{
DWORD result = ResumeThread(GetHANDLE());
if(result == (DWORD) -1)
{
ThrowLastOSError();
}
return result;
}
HWIN_EXPORT DWORD ThreadHandle::ExitCode() const
{
DWORD result = 0;
if(GetExitCodeThread(GetHANDLE(),&result) == 0)
{
ThrowLastOSError();
}
return result;
}
HWIN_EXPORT DWORD ThreadHandle::DoOnRun()
{
return 0;
}
// -----------------------------------------------------------------
// CurrentThreadData
// -----------------------------------------------------------------
HWIN_EXPORT CurrentThreadData::CurrentThreadData()
{
threadId = GetCurrentThreadId();
}
HWIN_EXPORT CurrentThreadData::~CurrentThreadData()
{
}
// -----------------------------------------------------------------
// CurrentThreadHandle
// -----------------------------------------------------------------
__declspec(thread) CurrentThreadData* CurrentThreadHandle::currentThreadData = nullptr;
HWIN_EXPORT void CurrentThreadHandle::InitializeThreadData()
{
if(currentThreadData == nullptr)
{
currentThreadData = new CurrentThreadData();
}
}
HWIN_EXPORT void CurrentThreadHandle::FinalizeThreadData()
{
if(currentThreadData != nullptr)
{
delete currentThreadData;
currentThreadData = nullptr;
}
}
HWIN_EXPORT CurrentThreadHandle::CurrentThreadHandle()
: Base(GetCurrentThread(),false)
{}
HWIN_EXPORT CurrentThreadHandle::ThreadPriority_t CurrentThreadHandle::ThreadPriority() const
{
int result = GetThreadPriority(GetHANDLE());
if(result == THREAD_PRIORITY_ERROR_RETURN)
{
ThrowLastOSError();
}
return ThreadPriority_t(result);
}
HWIN_EXPORT CurrentThreadHandle& CurrentThreadHandle::SetThreadPriority(ThreadPriority_t theThreadPriority)
{
if(::SetThreadPriority(GetHANDLE(),int(theThreadPriority)) == 0)
{
ThrowLastOSError();
}
return *this;
}
HWIN_EXPORT DWORD CurrentThreadHandle::Suspend()
{
DWORD result = SuspendThread(GetHANDLE());
if(result == (DWORD) -1)
{
ThrowLastOSError();
}
return result;
}
HWIN_EXPORT CurrentThreadHandle& CurrentThreadHandle::Sleep(DWORD milliSeconds)
{
::Sleep(milliSeconds);
return *this;
}
HWIN_EXPORT bool CurrentThreadHandle::Sleep(DWORD milliSeconds,bool alertable)
{
if(::SleepEx(milliSeconds,alertable?TRUE:FALSE) == WAIT_IO_COMPLETION)
{
return true;
}
return false;
}
};
};
};