Fixed bugs in the threading wrapper
This commit is contained in:
parent
972cfa0d39
commit
fe7fd6b0b3
|
@ -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();
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue