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.9 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);
}