Fixed merging errors

This commit is contained in:
dean11 2013-11-28 15:17:25 +01:00
parent cc4835a97b
commit 6e71b6ac54
5 changed files with 446 additions and 21 deletions

View File

@ -0,0 +1,37 @@
/////////////////////////////////////////////////////////////////////
// Created by [Dennis Andersen] [2013]
/////////////////////////////////////////////////////////////////////
#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_THREAD_OBJECT_H

View File

@ -0,0 +1,66 @@
/////////////////////////////////////////////////////////////////////
// Created by [Dennis Andersen] [2013]
/////////////////////////////////////////////////////////////////////
#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();
}

View File

@ -9,13 +9,9 @@
#include <thread> #include <thread>
#include <atomic> #include <atomic>
namespace Oyster class OysterMutex
{ {
namespace Thread public:
{
class OysterMutex
{
public:
OysterMutex(); OysterMutex();
OysterMutex(bool initialOwnership); OysterMutex(bool initialOwnership);
virtual~OysterMutex(); virtual~OysterMutex();
@ -25,13 +21,11 @@ namespace Oyster
/** Returns true if mutex is taken */ /** Returns true if mutex is taken */
bool IsTaken(); bool IsTaken();
private: private:
std::mutex mutex; std::mutex mutex;
std::thread::id id; std::thread::id id;
OysterMutex(const OysterMutex&); OysterMutex(const OysterMutex&);
}; };
}
}
#endif // !MISC_OYSTER_MUTEX_H #endif // !MISC_OYSTER_MUTEX_H

View File

@ -0,0 +1,47 @@
/////////////////////////////////////////////////////////////////////
// Created by [Dennis Andersen] [2013]
/////////////////////////////////////////////////////////////////////
#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;
public:
OysterThread();
OysterThread(const OysterThread& original);
const OysterThread& operator=(const OysterThread& original);
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_OYSTER_THREAD_H

View File

@ -0,0 +1,281 @@
/////////////////////////////////////////////////////////////////////
// Created by [Dennis Andersen] [2013]
/////////////////////////////////////////////////////////////////////
#include "OysterThread.h"
#include "OysterMutex.h"
#include "..\Utilities.h"
#include <thread>
#include <assert.h>
#include <atomic>
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_DEAD,
};
struct ThreadData
{
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.
std::thread::id callingThread; //<! The owner thread.
IThreadObject *owner; //<! The owner of the thread as IThread.
std::atomic<int> msec; //<! A timer in miliseconds.
//OysterMutex mutexLock; //<! The lock, locking the member variabls.
ThreadData() {}
~ThreadData() {}
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(const PrivateData& o)
{
threadData = o.threadData;
}
~PrivateData()
{
//@todo TODO: Make detatch avalible.
this->threadData->workerThread->detach();
this->threadData->owner = 0;
this->threadData->state = OYSTER_THREAD_STATE_DEAD;
}
};
#pragma endregion
int tempId = 0;
std::vector<int> IDS;
static void ThreadingFunction(StdSmartPointer<ThreadData> &origin)
{
bool shouldContinue;
StdSmartPointer<ThreadData> w = origin;
theBegining:
while(w->state == OYSTER_THREAD_STATE_STOPED)
{
std::this_thread::yield();
}
// w->mutexLock.LockMutex();
if(w->owner)
{
w->owner->ThreadEntry();
}
// w->mutexLock.UnlockMutex();
while (w->state != OYSTER_THREAD_STATE_STOPED && w->state != OYSTER_THREAD_STATE_DEAD)
{
// w->mutexLock.LockMutex();
{
if(w->owner)
{
shouldContinue = w->owner->DoWork();
}
}
// w->mutexLock.UnlockMutex();
if(!shouldContinue)
{
goto theEnd;
}
if(w->state == OYSTER_THREAD_STATE_DEAD)
{
goto theEnd;
}
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)
{
std::this_thread::yield();
}
}
if(w->state == OYSTER_THREAD_STATE_DEAD)
{
w->workerThread->detach();
return;
}
theEnd:
// w->mutexLock.LockMutex();
if(w->owner)
{
w->owner->ThreadExit();
}
// w->mutexLock.UnlockMutex();
w->state = OYSTER_THREAD_STATE_DEAD;
}
OysterThread::OysterThread()
{
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()
{
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;
//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)
{
this->privateData->threadData->state = OYSTER_THREAD_STATE_RUNNING;
}
return OYSTER_THREAD_ERROR_SUCCESS;
}
OYSTER_THREAD_ERROR OysterThread::Start()
{
if(!this->privateData->threadData->owner)
return OYSTER_THREAD_ERROR_FAILED;
if(!this->privateData->threadData->workerThread)
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;
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()
{
this->privateData->threadData->state = OYSTER_THREAD_STATE_DEAD;
}
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;
}