You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
4.8 KiB
218 lines
4.8 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
|
|
#include <process.h> |
|
|
|
#include "hsThread.h" |
|
#include "hsExceptions.h" |
|
#include "hsMemory.h" |
|
|
|
// typedef unsigned int __stdcall (*EntryPtCB)(void*); |
|
|
|
static DWORD __stdcall gEntryPoint(void* param) |
|
{ |
|
return ((hsThread*)param)->WinRun(); |
|
} |
|
|
|
static unsigned int __stdcall gEntryPointBT(void* param) |
|
{ |
|
return ((hsThread*)param)->WinRun(); |
|
} |
|
|
|
hsThread::hsThread(UInt32 stackSize) : fStackSize(stackSize), fQuit(false), fThreadH(nil), fQuitSemaH(nil) |
|
{ |
|
} |
|
|
|
hsThread::~hsThread() |
|
{ |
|
this->Stop(); |
|
} |
|
|
|
void hsThread::Start() |
|
{ |
|
if (fThreadH == nil) |
|
{ |
|
fQuitSemaH = ::CreateSemaphore(nil, 0, kPosInfinity32, nil); |
|
if (fQuitSemaH == nil) |
|
throw hsOSException(-1); |
|
|
|
#if 0 |
|
fThreadH = ::CreateThread(nil, fStackSize, gEntryPoint, this, 0, &fThreadId); |
|
#else |
|
fThreadH = (HANDLE)_beginthreadex(nil, fStackSize, gEntryPointBT, this, 0, (unsigned int*)&fThreadId); |
|
#endif |
|
if (fThreadH == nil) |
|
throw hsOSException(-1); |
|
} |
|
} |
|
|
|
void hsThread::Stop() |
|
{ |
|
if (fThreadH != nil) |
|
{ this->fQuit = true; |
|
|
|
if (fQuitSemaH != nil) |
|
::WaitForSingleObject(fQuitSemaH, INFINITE); // wait for the thread to quit |
|
|
|
::CloseHandle(fThreadH); |
|
fThreadH = nil; |
|
::CloseHandle(fQuitSemaH); |
|
fQuitSemaH = nil; |
|
} |
|
} |
|
|
|
DWORD hsThread::WinRun() |
|
{ |
|
DWORD result = this->Run(); |
|
|
|
::ReleaseSemaphore(fQuitSemaH, 1, nil); // signal that we've quit |
|
|
|
return result; |
|
} |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
void* hsThread::Alloc(size_t size) |
|
{ |
|
return HSMemory::New(size); |
|
} |
|
|
|
void hsThread::Free(void* p) |
|
{ |
|
HSMemory::Delete(p); |
|
} |
|
|
|
void hsThread::ThreadYield() |
|
{ |
|
// Don't know how to explicitly yield on WIN32 |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////////////// |
|
|
|
hsMutex::hsMutex() |
|
{ |
|
fMutexH = ::CreateMutex(nil, false, nil); |
|
if (fMutexH == nil) |
|
throw hsOSException(-1); |
|
} |
|
|
|
hsMutex::~hsMutex() |
|
{ |
|
::CloseHandle(fMutexH); |
|
} |
|
|
|
void hsMutex::Lock() |
|
{ |
|
DWORD state = ::WaitForSingleObject(fMutexH, INFINITE); |
|
hsAssert(state != WAIT_FAILED,"hsMutex::Lock -> Wait Failed"); |
|
hsAssert(state != WAIT_ABANDONED,"hsMutex::Lock -> Abandoned Mutex"); |
|
hsAssert(state != WAIT_TIMEOUT,"hsMutex::Lock -> Infinite Timeout expired?"); |
|
} |
|
|
|
hsBool hsMutex::TryLock() |
|
{ |
|
DWORD state = ::WaitForSingleObject(fMutexH, 0); |
|
hsAssert(state != WAIT_ABANDONED,"hsMutex::TryLock -> Abandoned Mutex"); |
|
return state == WAIT_OBJECT_0?true:false; |
|
} |
|
|
|
void hsMutex::Unlock() |
|
{ |
|
BOOL result = ::ReleaseMutex(fMutexH); |
|
hsAssert(result != 0, "hsMutex::Unlock Failed!"); |
|
|
|
} |
|
|
|
////////////////////////////////////////////////////////////////////////////// |
|
|
|
hsSemaphore::hsSemaphore(int initialValue, const char *name) |
|
{ |
|
fSemaH = ::CreateSemaphore(nil, initialValue, kPosInfinity32, name); |
|
if (fSemaH == nil) |
|
throw hsOSException(-1); |
|
} |
|
|
|
hsSemaphore::~hsSemaphore() |
|
{ |
|
::CloseHandle(fSemaH); |
|
} |
|
|
|
hsBool hsSemaphore::Wait(hsMilliseconds timeToWait) |
|
{ |
|
if (timeToWait == kPosInfinity32) |
|
timeToWait = INFINITE; |
|
|
|
DWORD result =::WaitForSingleObject(fSemaH, timeToWait); |
|
|
|
if (result == WAIT_OBJECT_0) |
|
return true; |
|
else |
|
{ hsThrowIfFalse(result == WAIT_TIMEOUT); |
|
return false; |
|
} |
|
} |
|
|
|
void hsSemaphore::Signal() |
|
{ |
|
::ReleaseSemaphore(fSemaH, 1, nil); |
|
} |
|
|
|
/////////////////////////////////////////////////////////////// |
|
|
|
hsEvent::hsEvent() |
|
{ |
|
fEvent = ::CreateEvent(nil,true,false,nil); |
|
if (fEvent == nil) |
|
throw hsOSException(-1); |
|
} |
|
|
|
hsEvent::~hsEvent() |
|
{ |
|
::CloseHandle(fEvent); |
|
} |
|
|
|
hsBool hsEvent::Wait(hsMilliseconds timeToWait) |
|
{ |
|
if (timeToWait == kPosInfinity32) |
|
timeToWait = INFINITE; |
|
|
|
DWORD result =::WaitForSingleObject(fEvent, timeToWait); |
|
|
|
if (result == WAIT_OBJECT_0) |
|
{ |
|
::ResetEvent(fEvent); |
|
return true; |
|
} |
|
else |
|
{ hsThrowIfFalse(result == WAIT_TIMEOUT); |
|
return false; |
|
} |
|
} |
|
|
|
void hsEvent::Signal() |
|
{ |
|
::SetEvent(fEvent); |
|
} |