reimplement task to not be buggy
This commit is contained in:
parent
ae92918d27
commit
fc77539bda
|
@ -53,9 +53,10 @@ int getOnlineCores (void)
|
||||||
|
|
||||||
class Task::Impl {
|
class Task::Impl {
|
||||||
private:
|
private:
|
||||||
sthread_t* _thread;
|
sthread_t* thread;
|
||||||
bool _isThreadRunning;
|
friend void thunkTaskProc(void* arg);
|
||||||
|
void taskProc();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Impl();
|
Impl();
|
||||||
~Impl();
|
~Impl();
|
||||||
|
@ -64,142 +65,144 @@ public:
|
||||||
void execute(const TWork &work, void *param);
|
void execute(const TWork &work, void *param);
|
||||||
void* finish();
|
void* finish();
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
void initialize();
|
||||||
|
|
||||||
slock_t *mutex;
|
slock_t *mutex;
|
||||||
scond_t *condWork;
|
scond_t *workCond;
|
||||||
|
bool workFlag, finishFlag;
|
||||||
TWork workFunc;
|
TWork workFunc;
|
||||||
void *workFuncParam;
|
void *workFuncParam;
|
||||||
void *ret;
|
void *ret;
|
||||||
bool exitThread;
|
bool exitThread;
|
||||||
|
bool started;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void taskProc(void *arg)
|
static void thunkTaskProc(void *arg)
|
||||||
{
|
{
|
||||||
Task::Impl *ctx = (Task::Impl *)arg;
|
Task::Impl *ctx = (Task::Impl *)arg;
|
||||||
|
ctx->taskProc();
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
void Task::Impl::taskProc()
|
||||||
slock_lock(ctx->mutex);
|
{
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
slock_lock(mutex);
|
||||||
|
|
||||||
while (ctx->workFunc == NULL && !ctx->exitThread) {
|
if(!workFlag)
|
||||||
scond_wait(ctx->condWork, ctx->mutex);
|
scond_wait(workCond, mutex);
|
||||||
}
|
workFlag = false;
|
||||||
|
|
||||||
if (ctx->workFunc != NULL) {
|
ret = workFunc(workFuncParam);
|
||||||
ctx->ret = ctx->workFunc(ctx->workFuncParam);
|
|
||||||
} else {
|
|
||||||
ctx->ret = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->workFunc = NULL;
|
finishFlag = true;
|
||||||
scond_signal(ctx->condWork);
|
scond_signal(workCond);
|
||||||
|
|
||||||
slock_unlock(ctx->mutex);
|
slock_unlock(mutex);
|
||||||
|
|
||||||
} while(!ctx->exitThread);
|
if(exitThread)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* killTask(void* task)
|
||||||
|
{
|
||||||
|
((Task::Impl*)task)->exitThread = true;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Impl::Impl()
|
Task::Impl::Impl()
|
||||||
|
: started(false)
|
||||||
{
|
{
|
||||||
_isThreadRunning = false;
|
|
||||||
workFunc = NULL;
|
|
||||||
workFuncParam = NULL;
|
|
||||||
ret = NULL;
|
|
||||||
exitThread = false;
|
|
||||||
|
|
||||||
mutex = slock_new();
|
|
||||||
condWork = scond_new();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Impl::~Impl()
|
Task::Impl::~Impl()
|
||||||
{
|
{
|
||||||
shutdown();
|
shutdown();
|
||||||
slock_free(mutex);
|
}
|
||||||
scond_free(condWork);
|
|
||||||
|
void Task::Impl::initialize()
|
||||||
|
{
|
||||||
|
thread = NULL;
|
||||||
|
workFunc = NULL;
|
||||||
|
workCond = NULL;
|
||||||
|
workFlag = finishFlag = false;
|
||||||
|
workFunc = NULL;
|
||||||
|
workFuncParam = NULL;
|
||||||
|
ret = NULL;
|
||||||
|
exitThread = false;
|
||||||
|
started = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::Impl::start(bool spinlock)
|
void Task::Impl::start(bool spinlock)
|
||||||
{
|
{
|
||||||
slock_lock(this->mutex);
|
initialize();
|
||||||
|
mutex = slock_new();
|
||||||
|
workCond = scond_new();
|
||||||
|
|
||||||
if (this->_isThreadRunning) {
|
slock_lock(mutex);
|
||||||
slock_unlock(this->mutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->workFunc = NULL;
|
thread = sthread_create(&thunkTaskProc,this);
|
||||||
this->workFuncParam = NULL;
|
started = true;
|
||||||
this->ret = NULL;
|
|
||||||
this->exitThread = false;
|
slock_unlock(mutex);
|
||||||
this->_thread = sthread_create(&taskProc,this);
|
}
|
||||||
this->_isThreadRunning = true;
|
|
||||||
|
void Task::Impl::shutdown()
|
||||||
|
{
|
||||||
|
if(!started) return;
|
||||||
|
|
||||||
|
execute(killTask,this);
|
||||||
|
finish();
|
||||||
|
|
||||||
|
started = false;
|
||||||
|
|
||||||
|
sthread_join(thread);
|
||||||
|
slock_free(mutex);
|
||||||
|
scond_free(workCond);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Task::Impl::finish()
|
||||||
|
{
|
||||||
|
//no work running; nothing to do (it's kind of lame that we call this under the circumstances)
|
||||||
|
if(!workFunc)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
slock_lock(mutex);
|
||||||
|
|
||||||
|
if(!finishFlag)
|
||||||
|
scond_wait(workCond, mutex);
|
||||||
|
finishFlag = false;
|
||||||
|
|
||||||
slock_unlock(this->mutex);
|
slock_unlock(this->mutex);
|
||||||
|
|
||||||
|
workFunc = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::Impl::execute(const TWork &work, void *param)
|
void Task::Impl::execute(const TWork &work, void *param)
|
||||||
{
|
{
|
||||||
slock_lock(this->mutex);
|
slock_lock(this->mutex);
|
||||||
|
|
||||||
if (work == NULL || !this->_isThreadRunning) {
|
workFunc = work;
|
||||||
slock_unlock(this->mutex);
|
workFuncParam = param;
|
||||||
return;
|
workFlag = true;
|
||||||
}
|
scond_signal(workCond);
|
||||||
|
|
||||||
this->workFunc = work;
|
|
||||||
this->workFuncParam = param;
|
|
||||||
scond_signal(this->condWork);
|
|
||||||
|
|
||||||
slock_unlock(this->mutex);
|
slock_unlock(this->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Task::Impl::finish()
|
|
||||||
{
|
|
||||||
void *returnValue = NULL;
|
|
||||||
|
|
||||||
slock_lock(this->mutex);
|
|
||||||
|
|
||||||
if (!this->_isThreadRunning) {
|
|
||||||
slock_unlock(this->mutex);
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (this->workFunc != NULL) {
|
|
||||||
scond_wait(this->condWork, this->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
returnValue = this->ret;
|
|
||||||
|
|
||||||
slock_unlock(this->mutex);
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Task::Impl::shutdown()
|
|
||||||
{
|
|
||||||
slock_lock(this->mutex);
|
|
||||||
|
|
||||||
if (!this->_isThreadRunning) {
|
|
||||||
slock_unlock(this->mutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->workFunc = NULL;
|
|
||||||
this->exitThread = true;
|
|
||||||
scond_signal(this->condWork);
|
|
||||||
|
|
||||||
slock_unlock(this->mutex);
|
|
||||||
|
|
||||||
sthread_join(this->_thread);
|
|
||||||
|
|
||||||
slock_lock(this->mutex);
|
|
||||||
this->_isThreadRunning = false;
|
|
||||||
slock_unlock(this->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Task::start(bool spinlock) { impl->start(spinlock); }
|
void Task::start(bool spinlock) { impl->start(spinlock); }
|
||||||
void Task::shutdown() { impl->shutdown(); }
|
void Task::shutdown() { impl->shutdown(); }
|
||||||
Task::Task() : impl(new Task::Impl()) {}
|
Task::Task() : impl(new Task::Impl()) {}
|
||||||
Task::~Task() { delete impl; }
|
Task::~Task()
|
||||||
|
{
|
||||||
|
delete impl;
|
||||||
|
}
|
||||||
void Task::execute(const TWork &work, void* param) { impl->execute(work,param); }
|
void Task::execute(const TWork &work, void* param) { impl->execute(work,param); }
|
||||||
void* Task::finish() { return impl->finish(); }
|
void* Task::finish() { return impl->finish(); }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue