Added a threading wrapper with basic functionality that needs real testing
This commit is contained in:
parent
1f27336b3f
commit
e4904870b3
Binary file not shown.
Binary file not shown.
33004
Code/Debug/bth.obj
33004
Code/Debug/bth.obj
File diff suppressed because it is too large
Load Diff
|
@ -150,12 +150,18 @@
|
||||||
<ClCompile Include="Resource\Loaders\CustomLoader.cpp" />
|
<ClCompile Include="Resource\Loaders\CustomLoader.cpp" />
|
||||||
<ClCompile Include="Resource\OResourceHandler.cpp" />
|
<ClCompile Include="Resource\OResourceHandler.cpp" />
|
||||||
<ClCompile Include="Resource\OResource.cpp" />
|
<ClCompile Include="Resource\OResource.cpp" />
|
||||||
|
<ClCompile Include="Thread\OysterMutex.cpp" />
|
||||||
|
<ClCompile Include="Thread\OysterThread_Impl.cpp" />
|
||||||
<ClCompile Include="Utilities.cpp" />
|
<ClCompile Include="Utilities.cpp" />
|
||||||
<ClCompile Include="WinTimer.cpp" />
|
<ClCompile Include="WinTimer.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Resource\OysterResource.h" />
|
<ClInclude Include="Resource\OysterResource.h" />
|
||||||
<ClInclude Include="Resource\OResource.h" />
|
<ClInclude Include="Resource\OResource.h" />
|
||||||
|
<ClInclude Include="Thread\IThreadObject.h" />
|
||||||
|
<ClInclude Include="Thread\OysterMutex.h" />
|
||||||
|
<ClInclude Include="Thread\OysterThread.h" />
|
||||||
|
<ClInclude Include="Thread\OysterThread_Impl.h" />
|
||||||
<ClInclude Include="Utilities-InlineImpl.h" />
|
<ClInclude Include="Utilities-InlineImpl.h" />
|
||||||
<ClInclude Include="Utilities.h" />
|
<ClInclude Include="Utilities.h" />
|
||||||
<ClInclude Include="WinTimer.h" />
|
<ClInclude Include="WinTimer.h" />
|
||||||
|
|
|
@ -33,6 +33,12 @@
|
||||||
<ClCompile Include="Resource\Loaders\CustomLoader.cpp">
|
<ClCompile Include="Resource\Loaders\CustomLoader.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Thread\OysterMutex.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Thread\OysterThread_Impl.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Utilities.h">
|
<ClInclude Include="Utilities.h">
|
||||||
|
@ -50,5 +56,17 @@
|
||||||
<ClInclude Include="Resource\OResource.h">
|
<ClInclude Include="Resource\OResource.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Thread\IThreadObject.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Thread\OysterMutex.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Thread\OysterThread.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Thread\OysterThread_Impl.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -47,7 +47,7 @@ namespace Oyster
|
||||||
static OResource* Reload (OResource* resource);
|
static OResource* Reload (OResource* resource);
|
||||||
static bool Release (OResource* resource);
|
static bool Release (OResource* resource);
|
||||||
|
|
||||||
Utility::DynamicMemory::RefCount resourceRef;
|
Utility::DynamicMemory::ReferenceCount resourceRef;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static OResource* ByteLoader (const wchar_t filename[], ResourceType type, OResource* old = 0);
|
static OResource* ByteLoader (const wchar_t filename[], ResourceType type, OResource* old = 0);
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef MISC_I_THREAD_OBJECT_H
|
||||||
|
#define MISC_I_THREAD_OBJECT_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Thread
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Inherit this class to get threading compatibility.
|
||||||
|
*/
|
||||||
|
class IThreadObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Override this to get notified when the thread is started.
|
||||||
|
*/
|
||||||
|
virtual void ThreadEntry() { }
|
||||||
|
/**
|
||||||
|
* Override this to get notified when the thread is about to exit.
|
||||||
|
*/
|
||||||
|
virtual void ThreadExit() { }
|
||||||
|
/**
|
||||||
|
* This function is required to get threading working.
|
||||||
|
*/
|
||||||
|
virtual bool DoWork ( ) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !MISC_I_WORKER_THREAD_H
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
#include "OysterMutex.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OysterMutex::OysterMutex()
|
||||||
|
{}
|
||||||
|
|
||||||
|
OysterMutex::OysterMutex(bool initialOwnership)
|
||||||
|
{
|
||||||
|
if(initialOwnership)
|
||||||
|
{
|
||||||
|
this->mutex.lock();
|
||||||
|
this->id = std::this_thread::get_id();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OysterMutex::~OysterMutex()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void OysterMutex::LockMutex()
|
||||||
|
{
|
||||||
|
if(std::this_thread::get_id() == this->id) return;
|
||||||
|
|
||||||
|
this->mutex.lock();
|
||||||
|
|
||||||
|
this->id = std::this_thread::get_id();
|
||||||
|
}
|
||||||
|
void OysterMutex::LockMutex(unsigned int msec)
|
||||||
|
{
|
||||||
|
if(std::this_thread::get_id() == this->id) return;
|
||||||
|
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
auto end = start + std::chrono::milliseconds(msec);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if(this->mutex.try_lock())
|
||||||
|
{
|
||||||
|
this->mutex.lock();
|
||||||
|
this->id = std::this_thread::get_id();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (std::chrono::high_resolution_clock::now() < end);
|
||||||
|
|
||||||
|
this->mutex.lock();
|
||||||
|
}
|
||||||
|
void OysterMutex::UnlockMutex()
|
||||||
|
{
|
||||||
|
//Let the owner unlock
|
||||||
|
if(std::this_thread::get_id() != this->id) return;
|
||||||
|
|
||||||
|
this->mutex.unlock();
|
||||||
|
this->id = std::thread::id();
|
||||||
|
|
||||||
|
}
|
||||||
|
bool OysterMutex::IsTaken()
|
||||||
|
{
|
||||||
|
return !this->mutex.try_lock();
|
||||||
|
}
|
||||||
|
void OysterMutex::Reset()
|
||||||
|
{
|
||||||
|
if(!this->mutex.try_lock())
|
||||||
|
this->mutex.unlock();
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef MISC_OYSTER_MUTEX_H
|
||||||
|
#define MISC_OYSTER_MUTEX_H
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
class OysterMutex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OysterMutex();
|
||||||
|
OysterMutex(bool initialOwnership);
|
||||||
|
virtual~OysterMutex();
|
||||||
|
void LockMutex();
|
||||||
|
void LockMutex(unsigned int timeSpan);
|
||||||
|
void UnlockMutex();
|
||||||
|
/** Returns true if mutex is taken */
|
||||||
|
bool IsTaken();
|
||||||
|
/** This function resets resource locking */
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex mutex;
|
||||||
|
std::thread::id id;
|
||||||
|
|
||||||
|
OysterMutex(const OysterMutex&);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !MISC_OYSTER_MUTEX_H
|
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef MISC_OYSTER_THREAD_H
|
||||||
|
#define MISC_OYSTER_THREAD_H
|
||||||
|
|
||||||
|
#include "IThreadObject.h"
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Thread
|
||||||
|
{
|
||||||
|
enum OYSTER_THREAD_ERROR
|
||||||
|
{
|
||||||
|
OYSTER_THREAD_ERROR_FAILED,
|
||||||
|
OYSTER_THREAD_ERROR_SUCCESS,
|
||||||
|
};
|
||||||
|
|
||||||
|
class OysterThread
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct PrivateData;
|
||||||
|
PrivateData *privateData;
|
||||||
|
|
||||||
|
OysterThread(const OysterThread& original);
|
||||||
|
const OysterThread& operator=(const OysterThread& original);
|
||||||
|
|
||||||
|
public:
|
||||||
|
OysterThread();
|
||||||
|
virtual~OysterThread();
|
||||||
|
|
||||||
|
OYSTER_THREAD_ERROR Create(IThreadObject* worker, bool start);
|
||||||
|
OYSTER_THREAD_ERROR Start();
|
||||||
|
void Stop();
|
||||||
|
void Pause();
|
||||||
|
void Pause(int mSec);
|
||||||
|
void Resume();
|
||||||
|
OYSTER_THREAD_ERROR Reset(IThreadObject* worker = 0);
|
||||||
|
void Terminate();
|
||||||
|
void Wait();
|
||||||
|
void Wait(int mSec);
|
||||||
|
OYSTER_THREAD_ERROR Swap(const OysterThread* other);
|
||||||
|
bool IsActive();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !MISC_I_OYSTER_THREAD_H
|
|
@ -0,0 +1,274 @@
|
||||||
|
#include "OysterThread.h"
|
||||||
|
#include <thread>
|
||||||
|
#include "OysterMutex.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include "..\Utilities.h"
|
||||||
|
|
||||||
|
using namespace Oyster::Thread;
|
||||||
|
using namespace Utility::DynamicMemory::SmartPointer;
|
||||||
|
|
||||||
|
|
||||||
|
#pragma region Declerations
|
||||||
|
|
||||||
|
struct ThreadData;
|
||||||
|
/** A typical Oyster thread function */
|
||||||
|
typedef void (*ThreadFunction)(StdSmartPointer<ThreadData>&);
|
||||||
|
|
||||||
|
enum OYSTER_THREAD_STATE
|
||||||
|
{
|
||||||
|
OYSTER_THREAD_STATE_RESET,
|
||||||
|
OYSTER_THREAD_STATE_RUNNING,
|
||||||
|
OYSTER_THREAD_STATE_PAUSED,
|
||||||
|
OYSTER_THREAD_STATE_STOPED,
|
||||||
|
OYSTER_THREAD_STATE_TERMINATED,
|
||||||
|
OYSTER_THREAD_STATE_DEAD,
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO: Add a threadStartPackage struct that contains all the necasary data to fire of a thread
|
||||||
|
struct ThreadData
|
||||||
|
{
|
||||||
|
OYSTER_THREAD_STATE state; //<! The current thread state.
|
||||||
|
StdSmartPointer<std::thread> workerThread; //<! The worker thread.
|
||||||
|
std::thread::id callingThread; //<! The owner thread.
|
||||||
|
IThreadObject *owner; //<! The owner of the thread as IThread.
|
||||||
|
int msec; //<! A timer in miliseconds.
|
||||||
|
OysterMutex mutexLock; //<! The lock, locking the member variabls.
|
||||||
|
|
||||||
|
ThreadData() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ThreadData(const ThreadData&){};
|
||||||
|
};
|
||||||
|
struct OysterThread::PrivateData
|
||||||
|
{
|
||||||
|
StdSmartPointer<ThreadData> threadData;
|
||||||
|
|
||||||
|
PrivateData()
|
||||||
|
:threadData(new ThreadData())
|
||||||
|
{
|
||||||
|
threadData->owner = 0;
|
||||||
|
threadData->workerThread = 0;
|
||||||
|
threadData->callingThread;
|
||||||
|
threadData->state = OYSTER_THREAD_STATE_STOPED;
|
||||||
|
}
|
||||||
|
~PrivateData()
|
||||||
|
{
|
||||||
|
//@todo TODO: Make detatch avalible.
|
||||||
|
//this->threadData->workerThread->detach();
|
||||||
|
|
||||||
|
this->threadData->owner = 0;
|
||||||
|
|
||||||
|
this->threadData->state = OYSTER_THREAD_STATE_DEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void ThreadingFunction(StdSmartPointer<ThreadData> &origin)
|
||||||
|
{
|
||||||
|
bool shouldContinue;
|
||||||
|
StdSmartPointer<ThreadData> w = origin;
|
||||||
|
|
||||||
|
theBegining:
|
||||||
|
|
||||||
|
while(w->state == OYSTER_THREAD_STATE_STOPED);
|
||||||
|
w->mutexLock.LockMutex();
|
||||||
|
w->owner->ThreadEntry();
|
||||||
|
w->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
while (w->state != OYSTER_THREAD_STATE_STOPED && w->state != OYSTER_THREAD_STATE_DEAD)
|
||||||
|
{
|
||||||
|
|
||||||
|
w->mutexLock.LockMutex();
|
||||||
|
{
|
||||||
|
shouldContinue = w->owner->DoWork();
|
||||||
|
}
|
||||||
|
w->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
if(!shouldContinue)
|
||||||
|
{
|
||||||
|
goto theEnd;
|
||||||
|
}
|
||||||
|
if(w->state == OYSTER_THREAD_STATE_TERMINATED)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(w->state == OYSTER_THREAD_STATE_RESET)
|
||||||
|
{
|
||||||
|
goto theBegining;
|
||||||
|
}
|
||||||
|
else if(w->msec > 0)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(w->msec));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (w->state == OYSTER_THREAD_STATE_PAUSED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(w->state == OYSTER_THREAD_STATE_DEAD)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
theEnd:
|
||||||
|
|
||||||
|
w->mutexLock.LockMutex();
|
||||||
|
w->owner->ThreadExit();
|
||||||
|
w->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
w->state = OYSTER_THREAD_STATE_DEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
OysterThread::OysterThread()
|
||||||
|
{
|
||||||
|
this->privateData = new PrivateData();
|
||||||
|
}
|
||||||
|
OysterThread::~OysterThread()
|
||||||
|
{
|
||||||
|
delete this->privateData;
|
||||||
|
this->privateData = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Create(IThreadObject* worker, bool start)
|
||||||
|
{
|
||||||
|
if(!this->privateData) return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
if(this->privateData->threadData->workerThread) return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
|
||||||
|
this->privateData->threadData->owner = worker;
|
||||||
|
|
||||||
|
ThreadFunction fnc = ThreadingFunction;
|
||||||
|
|
||||||
|
/*
|
||||||
|
//Create a lambda function with current worker instance to fire of the thread
|
||||||
|
#if defined(DEBUG) || defined (_DEBUG)
|
||||||
|
ThreadFunction fnc = [](ThreadData* w) -> void
|
||||||
|
{
|
||||||
|
while(w->state == OYSTER_THREAD_STATE_STOPED);
|
||||||
|
|
||||||
|
w->owner->ThreadEntry();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
w->mutexLock.LockMutex();
|
||||||
|
w->owner->DoWork();
|
||||||
|
w->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
w->mutexLock.LockMutex();
|
||||||
|
w->owner->ThreadExit();
|
||||||
|
w->mutexLock.UnlockMutex();
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
ThreadFunction fnc = ThreadingFunction;
|
||||||
|
//ThreadFunction fnc = THREAD_LAMBDA_FUNCTION_CREATION;
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Maby move this thread creation to a seperate Start() function because std::thread fires the thread when it is created. :(
|
||||||
|
this->privateData->threadData->workerThread = new std::thread(fnc, this->privateData->threadData);
|
||||||
|
|
||||||
|
if(!this->privateData->threadData->workerThread)
|
||||||
|
return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
|
||||||
|
if(start)
|
||||||
|
{
|
||||||
|
//@todo TODO: No need to lock since the other thread end is only reading this value. Worst case scenario is n lost cycles.
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
|
||||||
|
}
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Start()
|
||||||
|
{
|
||||||
|
if(!this->privateData->threadData->workerThread)
|
||||||
|
return OYSTER_THREAD_ERROR_FAILED;
|
||||||
|
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
void OysterThread::Stop()
|
||||||
|
{
|
||||||
|
this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_STOPED;
|
||||||
|
this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
void OysterThread::Pause()
|
||||||
|
{
|
||||||
|
this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED;
|
||||||
|
this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
void OysterThread::Pause(int msec)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(std::this_thread::get_id() == this->privateData->threadData->workerThread->get_id())
|
||||||
|
{
|
||||||
|
this->privateData->threadData->msec = msec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED;
|
||||||
|
this->privateData->threadData->msec = msec;
|
||||||
|
this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void OysterThread::Resume()
|
||||||
|
{
|
||||||
|
this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
|
||||||
|
this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
}
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Reset(IThreadObject* worker)
|
||||||
|
{
|
||||||
|
this->privateData->threadData->mutexLock.LockMutex();
|
||||||
|
if(worker)
|
||||||
|
{
|
||||||
|
this->privateData->threadData->owner = worker;
|
||||||
|
}
|
||||||
|
this->privateData->threadData->callingThread = std::this_thread::get_id();
|
||||||
|
this->privateData->threadData->msec = 0;
|
||||||
|
this->privateData->threadData->mutexLock.UnlockMutex();
|
||||||
|
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
void OysterThread::Terminate()
|
||||||
|
{
|
||||||
|
delete this->privateData->threadData->workerThread;
|
||||||
|
this->privateData->threadData->mutexLock.Reset();
|
||||||
|
this->privateData->threadData->workerThread = 0;
|
||||||
|
this->privateData->threadData->callingThread = std::thread::id();
|
||||||
|
this->privateData->threadData->msec = 0;
|
||||||
|
this->privateData->threadData->state = OYSTER_THREAD_STATE_STOPED;
|
||||||
|
}
|
||||||
|
void OysterThread::Wait()
|
||||||
|
{
|
||||||
|
if(this->privateData->threadData->state == OYSTER_THREAD_STATE_DEAD)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->privateData->threadData->workerThread->get_id() == std::this_thread::get_id()) return;
|
||||||
|
|
||||||
|
this->privateData->threadData->workerThread->join();
|
||||||
|
}
|
||||||
|
void OysterThread::Wait(int msec)
|
||||||
|
{
|
||||||
|
if(this->privateData->threadData->workerThread->get_id() == std::this_thread::get_id()) return;
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(msec));
|
||||||
|
}
|
||||||
|
OYSTER_THREAD_ERROR OysterThread::Swap(const OysterThread* other)
|
||||||
|
{
|
||||||
|
this->privateData->threadData->workerThread->swap(*other->privateData->threadData->workerThread);
|
||||||
|
return OYSTER_THREAD_ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
bool OysterThread::IsActive()
|
||||||
|
{
|
||||||
|
if (this->privateData->threadData->state == OYSTER_THREAD_STATE_RUNNING)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef INCLUDE_GUARD_OYSTER_THREAD_H
|
||||||
|
#define INCLUDE_GUARD_OYSTER_THREAD_H
|
||||||
|
|
||||||
|
#include "IOysterThread.h"
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace Oyster
|
||||||
|
{
|
||||||
|
namespace Thread
|
||||||
|
{
|
||||||
|
//class OysterThread :public IOysterThread
|
||||||
|
//{
|
||||||
|
//private:
|
||||||
|
// std::thread thread; //<! The worker thread.
|
||||||
|
// IWorkerThread *owner; //<! The owner of the thread as IThread
|
||||||
|
//
|
||||||
|
//public:
|
||||||
|
// bool Wait();
|
||||||
|
// bool Suspend();
|
||||||
|
// void Resume();
|
||||||
|
// bool Kill();
|
||||||
|
// bool IsActive();
|
||||||
|
// bool Reset();
|
||||||
|
// bool StartThread()
|
||||||
|
// {
|
||||||
|
// this->owner->ThreadEntry();
|
||||||
|
//
|
||||||
|
// while (true)
|
||||||
|
// {
|
||||||
|
// this->owner->DoWork();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// this->owner->ThreadExit();
|
||||||
|
// }
|
||||||
|
//};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !INCLUDE_GUARD_OYSTER_THREAD_H
|
|
@ -2,6 +2,7 @@
|
||||||
// Inline and template implementations for
|
// Inline and template implementations for
|
||||||
// the Utility Collection of Miscellanious Handy Functions
|
// the Utility Collection of Miscellanious Handy Functions
|
||||||
// © Dan Andersson 2013
|
// © Dan Andersson 2013
|
||||||
|
// © Dennis Andersen 2013 TODO: Is this correct?
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef UTILITIES_INLINE_IMPL_H
|
#ifndef UTILITIES_INLINE_IMPL_H
|
||||||
|
@ -149,8 +150,7 @@ namespace Utility
|
||||||
return this->ownedArray != NULL;
|
return this->ownedArray != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>Type* UniqueArray<Type>::Release()
|
||||||
Type* UniqueArray<Type>::Release()
|
|
||||||
{
|
{
|
||||||
Type *copy = this->ownedArray;
|
Type *copy = this->ownedArray;
|
||||||
this->ownedArray = NULL;
|
this->ownedArray = NULL;
|
||||||
|
@ -162,6 +162,113 @@ namespace Utility
|
||||||
{
|
{
|
||||||
return this->operator bool();
|
return this->operator bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace SmartPointer
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
void StdSmartPointer<T>::Destroy()
|
||||||
|
{
|
||||||
|
delete this->_rc;
|
||||||
|
this->_rc = NULL;
|
||||||
|
delete this->_ptr;
|
||||||
|
this->_ptr = NULL;
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>::StdSmartPointer()
|
||||||
|
:_rc(0), _ptr(0)
|
||||||
|
{ }
|
||||||
|
template<typename T> StdSmartPointer<T>::StdSmartPointer(T* p)
|
||||||
|
:_ptr(p)
|
||||||
|
{
|
||||||
|
this->_rc = new ReferenceCount();
|
||||||
|
this->_rc->Incref();
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>::StdSmartPointer(const StdSmartPointer& d)
|
||||||
|
:_ptr(d._ptr), _rc(d._rc)
|
||||||
|
{
|
||||||
|
if(this->_rc)
|
||||||
|
this->_rc->Incref();
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>::~StdSmartPointer()
|
||||||
|
{
|
||||||
|
if (this->_rc && this->_rc->Decref() == 0)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>& StdSmartPointer<T>::operator= (const StdSmartPointer<T>& p)
|
||||||
|
{
|
||||||
|
if (this != &p)
|
||||||
|
{
|
||||||
|
//Last to go?
|
||||||
|
if(this->_rc && this->_rc->Release() == 0)
|
||||||
|
{
|
||||||
|
//Call child specific
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_ptr = p._ptr;
|
||||||
|
this->_rc = p._rc;
|
||||||
|
this->_rc->Add();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename T> StdSmartPointer<T>& StdSmartPointer<T>::operator= (T* p)
|
||||||
|
{
|
||||||
|
if (this->_ptr != p)
|
||||||
|
{
|
||||||
|
//Last to go?
|
||||||
|
if(this->_rc)
|
||||||
|
{
|
||||||
|
if(this->_rc->Decref() == 0)
|
||||||
|
{
|
||||||
|
//Call child specific
|
||||||
|
Destroy();
|
||||||
|
this->_rc = new ReferenceCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this->_rc = new ReferenceCount();
|
||||||
|
|
||||||
|
this->_ptr = p;
|
||||||
|
this->_rc->Incref();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
template<typename T> inline bool StdSmartPointer<T>::operator== (const StdSmartPointer<T>& d)
|
||||||
|
{
|
||||||
|
return d._ptr == this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline bool StdSmartPointer<T>::operator== (const T& p)
|
||||||
|
{
|
||||||
|
return &p == this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline T& StdSmartPointer<T>::operator* ()
|
||||||
|
{
|
||||||
|
return *this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline T* StdSmartPointer<T>::operator-> ()
|
||||||
|
{
|
||||||
|
return this->_ptr;
|
||||||
|
}
|
||||||
|
template<typename T> inline StdSmartPointer<T>::operator T* ()
|
||||||
|
{
|
||||||
|
return this->_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connected pointer */
|
||||||
|
template<typename T> inline T* StdSmartPointer<T>::Get()
|
||||||
|
{
|
||||||
|
return this->_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if the pointer is valid (not NULL)
|
||||||
|
Returns true for valid, else false. */
|
||||||
|
template<typename T> inline bool StdSmartPointer<T>::IsValid()
|
||||||
|
{
|
||||||
|
return (this->_ptr != NULL) ? true : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
// Utility Collection of Miscellanious Handy Functions
|
// Utility Collection of Miscellanious Handy Functions
|
||||||
// © Dan Andersson 2013
|
// © Dan Andersson 2013
|
||||||
|
// © Dennis Andersen 2013
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef UTILITIES_H
|
#ifndef UTILITIES_H
|
||||||
|
@ -106,20 +107,62 @@ namespace Utility
|
||||||
mutable Type *ownedArray;
|
mutable Type *ownedArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RefCount
|
struct ReferenceCount
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RefCount() :count(0) { }
|
ReferenceCount() :count(0) { }
|
||||||
RefCount(const RefCount& o) { count = o.count; }
|
ReferenceCount(const ReferenceCount& o) { count = o.count; }
|
||||||
const RefCount& operator=(const RefCount& o) { count = o.count; return *this;}
|
inline const ReferenceCount& operator=(const ReferenceCount& o) { count = o.count; return *this;}
|
||||||
void Incref() { this->count++; }
|
inline void Incref() { this->count++; }
|
||||||
void Incref(int c) { this->count += c; }
|
inline void Incref(int c) { this->count += c; }
|
||||||
int Decref() { return --this->count;}
|
inline int Decref() { return --this->count;}
|
||||||
void Reset() { this->count = 0; }
|
inline void Reset() { this->count = 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace SmartPointer
|
||||||
|
{
|
||||||
|
//! Smart pointer for a regular object.
|
||||||
|
/**
|
||||||
|
* Regular objects, objects that is deleted normaly (ie not COM objects, or array pointers)
|
||||||
|
* can use this class to easy the use of dynamic memory
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
struct StdSmartPointer
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ReferenceCount *_rc;
|
||||||
|
T *_ptr;
|
||||||
|
|
||||||
|
/** Destroys the pointer and returns the memory allocated. */
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
public:
|
||||||
|
StdSmartPointer();
|
||||||
|
StdSmartPointer(T* p);
|
||||||
|
StdSmartPointer(const StdSmartPointer& d);
|
||||||
|
virtual~StdSmartPointer();
|
||||||
|
StdSmartPointer<T>& operator= (const StdSmartPointer<T>& p);
|
||||||
|
StdSmartPointer<T>& operator= (T* p);
|
||||||
|
bool operator== (const StdSmartPointer<T>& d);
|
||||||
|
bool operator== (const T& p);
|
||||||
|
T& operator* ();
|
||||||
|
T* operator-> ();
|
||||||
|
operator T* ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connected pointer */
|
||||||
|
T* Get();
|
||||||
|
|
||||||
|
/** Checks if the pointer is valid (not NULL)
|
||||||
|
Returns true for valid, else false. */
|
||||||
|
bool IsValid();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace String
|
namespace String
|
||||||
|
|
Loading…
Reference in New Issue