Fixed bugs in the threading wrapper

This commit is contained in:
dean11 2013-11-27 21:47:32 +01:00
parent 972cfa0d39
commit fe7fd6b0b3
6 changed files with 86 additions and 69 deletions

View File

@ -64,8 +64,3 @@ bool OysterMutex::IsTaken()
{ {
return !this->mutex.try_lock(); return !this->mutex.try_lock();
} }
void OysterMutex::Reset()
{
if(!this->mutex.try_lock())
this->mutex.unlock();
}

View File

@ -20,8 +20,6 @@ public:
void UnlockMutex(); void UnlockMutex();
/** Returns true if mutex is taken */ /** Returns true if mutex is taken */
bool IsTaken(); bool IsTaken();
/** This function resets resource locking */
void Reset();
private: private:
std::mutex mutex; std::mutex mutex;

View File

@ -6,7 +6,6 @@
#define MISC_OYSTER_THREAD_H #define MISC_OYSTER_THREAD_H
#include "IThreadObject.h" #include "IThreadObject.h"
namespace Oyster namespace Oyster
{ {
namespace Thread namespace Thread
@ -23,11 +22,10 @@ namespace Oyster
struct PrivateData; struct PrivateData;
PrivateData *privateData; PrivateData *privateData;
OysterThread(const OysterThread& original);
const OysterThread& operator=(const OysterThread& original);
public: public:
OysterThread(); OysterThread();
OysterThread(const OysterThread& original);
const OysterThread& operator=(const OysterThread& original);
virtual~OysterThread(); virtual~OysterThread();
OYSTER_THREAD_ERROR Create(IThreadObject* worker, bool start); OYSTER_THREAD_ERROR Create(IThreadObject* worker, bool start);

View File

@ -7,6 +7,7 @@
#include "..\Utilities.h" #include "..\Utilities.h"
#include <thread> #include <thread>
#include <assert.h> #include <assert.h>
#include <atomic>
using namespace Oyster::Thread; using namespace Oyster::Thread;
using namespace Utility::DynamicMemory::SmartPointer; using namespace Utility::DynamicMemory::SmartPointer;
@ -24,23 +25,22 @@ using namespace Utility::DynamicMemory::SmartPointer;
OYSTER_THREAD_STATE_RUNNING, OYSTER_THREAD_STATE_RUNNING,
OYSTER_THREAD_STATE_PAUSED, OYSTER_THREAD_STATE_PAUSED,
OYSTER_THREAD_STATE_STOPED, OYSTER_THREAD_STATE_STOPED,
OYSTER_THREAD_STATE_TERMINATED,
OYSTER_THREAD_STATE_DEAD, OYSTER_THREAD_STATE_DEAD,
}; };
//TODO: Add a threadStartPackage struct that contains all the necasary data to fire of a thread
struct ThreadData struct ThreadData
{ {
OYSTER_THREAD_STATE state; //<! The current thread state. std::atomic<OYSTER_THREAD_STATE> state; //<! The current thread state.
//OYSTER_THREAD_STATE state; //<! The current thread state.
StdSmartPointer<std::thread> workerThread; //<! The worker thread. StdSmartPointer<std::thread> workerThread; //<! The worker thread.
std::thread::id callingThread; //<! The owner thread. std::thread::id callingThread; //<! The owner thread.
IThreadObject *owner; //<! The owner of the thread as IThread. IThreadObject *owner; //<! The owner of the thread as IThread.
int msec; //<! A timer in miliseconds. std::atomic<int> msec; //<! A timer in miliseconds.
OysterMutex mutexLock; //<! The lock, locking the member variabls. //OysterMutex mutexLock; //<! The lock, locking the member variabls.
ThreadData() {} ThreadData() {}
~ThreadData() {}
private:
ThreadData(const ThreadData&) {}; ThreadData(const ThreadData&) {};
}; };
struct OysterThread::PrivateData struct OysterThread::PrivateData
@ -55,6 +55,10 @@ using namespace Utility::DynamicMemory::SmartPointer;
threadData->callingThread; threadData->callingThread;
threadData->state = OYSTER_THREAD_STATE_STOPED; threadData->state = OYSTER_THREAD_STATE_STOPED;
} }
PrivateData(const PrivateData& o)
{
threadData = o.threadData;
}
~PrivateData() ~PrivateData()
{ {
//@todo TODO: Make detatch avalible. //@todo TODO: Make detatch avalible.
@ -70,35 +74,46 @@ using namespace Utility::DynamicMemory::SmartPointer;
#pragma endregion #pragma endregion
int tempId = 0;
std::vector<int> IDS;
static void ThreadingFunction(StdSmartPointer<ThreadData> &origin) static void ThreadingFunction(StdSmartPointer<ThreadData> &origin)
{ {
bool shouldContinue; bool shouldContinue;
StdSmartPointer<ThreadData> w = origin; StdSmartPointer<ThreadData> w = origin;
theBegining: theBegining:
while(w->state == OYSTER_THREAD_STATE_STOPED); while(w->state == OYSTER_THREAD_STATE_STOPED)
w->mutexLock.LockMutex(); {
std::this_thread::yield();
}
// w->mutexLock.LockMutex();
if(w->owner)
{
w->owner->ThreadEntry(); w->owner->ThreadEntry();
w->mutexLock.UnlockMutex(); }
// w->mutexLock.UnlockMutex();
while (w->state != OYSTER_THREAD_STATE_STOPED && w->state != OYSTER_THREAD_STATE_DEAD) while (w->state != OYSTER_THREAD_STATE_STOPED && w->state != OYSTER_THREAD_STATE_DEAD)
{ {
// w->mutexLock.LockMutex();
w->mutexLock.LockMutex(); {
if(w->owner)
{ {
shouldContinue = w->owner->DoWork(); shouldContinue = w->owner->DoWork();
} }
w->mutexLock.UnlockMutex(); }
// w->mutexLock.UnlockMutex();
if(!shouldContinue) if(!shouldContinue)
{ {
goto theEnd; goto theEnd;
} }
if(w->state == OYSTER_THREAD_STATE_TERMINATED) if(w->state == OYSTER_THREAD_STATE_DEAD)
{ {
return; goto theEnd;
} }
else if(w->state == OYSTER_THREAD_STATE_RESET) else if(w->state == OYSTER_THREAD_STATE_RESET)
{ {
@ -109,19 +124,26 @@ theBegining:
std::this_thread::sleep_for(std::chrono::milliseconds(w->msec)); std::this_thread::sleep_for(std::chrono::milliseconds(w->msec));
} }
while (w->state == OYSTER_THREAD_STATE_PAUSED); while (w->state == OYSTER_THREAD_STATE_PAUSED)
{
std::this_thread::yield();
}
} }
if(w->state == OYSTER_THREAD_STATE_DEAD) if(w->state == OYSTER_THREAD_STATE_DEAD)
{ {
w->workerThread->detach();
return; return;
} }
theEnd: theEnd:
w->mutexLock.LockMutex(); // w->mutexLock.LockMutex();
if(w->owner)
{
w->owner->ThreadExit(); w->owner->ThreadExit();
w->mutexLock.UnlockMutex(); }
// w->mutexLock.UnlockMutex();
w->state = OYSTER_THREAD_STATE_DEAD; w->state = OYSTER_THREAD_STATE_DEAD;
} }
@ -130,6 +152,14 @@ OysterThread::OysterThread()
{ {
this->privateData = new PrivateData(); this->privateData = new PrivateData();
} }
OysterThread::OysterThread(const OysterThread& original)
{
this->privateData = new PrivateData(*original.privateData);
}
const OysterThread& OysterThread::operator=(const OysterThread& original)
{
return *this;
}
OysterThread::~OysterThread() OysterThread::~OysterThread()
{ {
delete this->privateData; delete this->privateData;
@ -153,30 +183,33 @@ OYSTER_THREAD_ERROR OysterThread::Create(IThreadObject* worker, bool start)
if(start) 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; this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
} }
return OYSTER_THREAD_ERROR_SUCCESS; return OYSTER_THREAD_ERROR_SUCCESS;
} }
OYSTER_THREAD_ERROR OysterThread::Start() OYSTER_THREAD_ERROR OysterThread::Start()
{ {
if(!this->privateData->threadData->owner)
return OYSTER_THREAD_ERROR_FAILED;
if(!this->privateData->threadData->workerThread) if(!this->privateData->threadData->workerThread)
return OYSTER_THREAD_ERROR_FAILED; return OYSTER_THREAD_ERROR_FAILED;
if(this->privateData->threadData->state == OYSTER_THREAD_STATE_DEAD)
return OYSTER_THREAD_ERROR_FAILED;
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING; this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
return OYSTER_THREAD_ERROR_SUCCESS; return OYSTER_THREAD_ERROR_SUCCESS;
} }
void OysterThread::Stop() void OysterThread::Stop()
{ {
this->privateData->threadData->mutexLock.LockMutex(); //this->privateData->threadData->mutexLock.LockMutex();
this->privateData->threadData->state = OYSTER_THREAD_STATE_STOPED; this->privateData->threadData->state = OYSTER_THREAD_STATE_STOPED;
this->privateData->threadData->mutexLock.UnlockMutex(); //this->privateData->threadData->mutexLock.UnlockMutex();
} }
void OysterThread::Pause() void OysterThread::Pause()
{ {
this->privateData->threadData->mutexLock.LockMutex(); //this->privateData->threadData->mutexLock.LockMutex();
this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED; this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED;
this->privateData->threadData->mutexLock.UnlockMutex(); //this->privateData->threadData->mutexLock.UnlockMutex();
} }
void OysterThread::Pause(int msec) void OysterThread::Pause(int msec)
{ {
@ -187,39 +220,34 @@ void OysterThread::Pause(int msec)
} }
else else
{ {
this->privateData->threadData->mutexLock.LockMutex(); //this->privateData->threadData->mutexLock.LockMutex();
this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED; this->privateData->threadData->state = OYSTER_THREAD_STATE_PAUSED;
this->privateData->threadData->msec = msec; this->privateData->threadData->msec = msec;
this->privateData->threadData->mutexLock.UnlockMutex(); //this->privateData->threadData->mutexLock.UnlockMutex();
} }
} }
void OysterThread::Resume() void OysterThread::Resume()
{ {
this->privateData->threadData->mutexLock.LockMutex(); // this->privateData->threadData->mutexLock.LockMutex();
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING; this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
this->privateData->threadData->mutexLock.UnlockMutex(); // this->privateData->threadData->mutexLock.UnlockMutex();
} }
OYSTER_THREAD_ERROR OysterThread::Reset(IThreadObject* worker) OYSTER_THREAD_ERROR OysterThread::Reset(IThreadObject* worker)
{ {
this->privateData->threadData->mutexLock.LockMutex(); // this->privateData->threadData->mutexLock.LockMutex();
if(worker) if(worker)
{ {
this->privateData->threadData->owner = worker; this->privateData->threadData->owner = worker;
} }
this->privateData->threadData->callingThread = std::this_thread::get_id(); this->privateData->threadData->callingThread = std::this_thread::get_id();
this->privateData->threadData->msec = 0; this->privateData->threadData->msec = 0;
this->privateData->threadData->mutexLock.UnlockMutex(); // this->privateData->threadData->mutexLock.UnlockMutex();
return OYSTER_THREAD_ERROR_SUCCESS; return OYSTER_THREAD_ERROR_SUCCESS;
} }
void OysterThread::Terminate() void OysterThread::Terminate()
{ {
delete this->privateData->threadData->workerThread; this->privateData->threadData->state = OYSTER_THREAD_STATE_DEAD;
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() void OysterThread::Wait()
{ {

View File

@ -165,8 +165,7 @@ namespace Utility
namespace SmartPointer namespace SmartPointer
{ {
template<typename T> template<typename T> void StdSmartPointer<T>::Destroy()
void StdSmartPointer<T>::Destroy()
{ {
delete this->_rc; delete this->_rc;
this->_rc = NULL; this->_rc = NULL;
@ -200,7 +199,7 @@ namespace Utility
if (this != &p) if (this != &p)
{ {
//Last to go? //Last to go?
if(this->_rc && this->_rc->Release() == 0) if(this->_rc && this->_rc->Decref() == 0)
{ {
//Call child specific //Call child specific
Destroy(); Destroy();
@ -208,7 +207,7 @@ namespace Utility
this->_ptr = p._ptr; this->_ptr = p._ptr;
this->_rc = p._rc; this->_rc = p._rc;
this->_rc->Add(); this->_rc->Incref();
} }
return *this; return *this;
} }
@ -254,16 +253,14 @@ namespace Utility
{ {
return this->_ptr; return this->_ptr;
} }
template<typename T> inline StdSmartPointer<T>::operator bool()
/** {
* Returns the connected pointer */ return (this->_ptr != 0);
}
template<typename T> inline T* StdSmartPointer<T>::Get() template<typename T> inline T* StdSmartPointer<T>::Get()
{ {
return this->_ptr; 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() template<typename T> inline bool StdSmartPointer<T>::IsValid()
{ {
return (this->_ptr != NULL) ? true : false; return (this->_ptr != NULL) ? true : false;

View File

@ -151,6 +151,7 @@ namespace Utility
T& operator* (); T& operator* ();
T* operator-> (); T* operator-> ();
operator T* (); operator T* ();
operator bool();
/** /**
* Returns the connected pointer */ * Returns the connected pointer */