first commit
This commit is contained in:
135
include/platform/thread/thread_controller.h
Normal file
135
include/platform/thread/thread_controller.h
Normal file
@ -0,0 +1,135 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __THREAD_CONTROLLER__
|
||||
#define __THREAD_CONTROLLER__
|
||||
|
||||
|
||||
#include "thread/atomic_value.h"
|
||||
#include "thread/thread_event.h"
|
||||
#include "thread/future.h"
|
||||
#include "thread/thread.h"
|
||||
#include "thread/mutex.h"
|
||||
#include "container/nlist.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <typename Target> struct DefaultControllerPolicy
|
||||
{
|
||||
static const bool use_event = true; // use thread event to sleep the worker thread
|
||||
static const bool own_target = false; // the controller owns the target object and is responsible for deleting it
|
||||
|
||||
static void Update(Target *) {}
|
||||
};
|
||||
|
||||
template <typename Target, class Policy = DefaultControllerPolicy <Target> > class Controller
|
||||
{
|
||||
public:
|
||||
|
||||
struct Command
|
||||
{
|
||||
Atomic32 dispose;
|
||||
virtual void Execute(Target *target) = 0;
|
||||
|
||||
Command() : dispose(1) {}
|
||||
virtual ~Command() {}
|
||||
};
|
||||
|
||||
template <class Result> struct CommandWithResult : public Command
|
||||
{
|
||||
Future <Result> future_result;
|
||||
CommandWithResult() { this->dispose.Set(0); }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
struct WorkerThread : public Thread
|
||||
{
|
||||
Target *target;
|
||||
|
||||
Atomic32 running;
|
||||
|
||||
Mutex command_mutex;
|
||||
Event command_event;
|
||||
|
||||
AutoList <Command *> command_queue;
|
||||
|
||||
void Execute()
|
||||
{
|
||||
forever
|
||||
{
|
||||
Policy::Update(target);
|
||||
{
|
||||
MutexLock lock(&command_mutex);
|
||||
while (command_queue.GetCount() > 0)
|
||||
{
|
||||
command_queue[0]->Execute(target);
|
||||
while (command_queue[0]->dispose.Get() != 1)
|
||||
; // spin lock on command dispose flag
|
||||
command_queue.RemoveAt(0);
|
||||
}
|
||||
if (running.Get() != 1)
|
||||
break;
|
||||
}
|
||||
if (Policy::use_event)
|
||||
command_event.Wait();
|
||||
}
|
||||
running.Set(0);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
running.Set(2);
|
||||
if (Policy::use_event)
|
||||
command_event.Trigger();
|
||||
while (running.Get() != 0); // spinlock
|
||||
}
|
||||
|
||||
WorkerThread(Target *t) : target(t), running(1) {}
|
||||
~WorkerThread()
|
||||
{
|
||||
if (Policy::own_target)
|
||||
delete target;
|
||||
}
|
||||
};
|
||||
|
||||
WorkerThread worker;
|
||||
|
||||
public:
|
||||
|
||||
void QueueCommand(Command *c)
|
||||
{
|
||||
{
|
||||
MutexLock lock(&worker.command_mutex);
|
||||
worker.command_queue.Append(c);
|
||||
}
|
||||
worker.command_event.Trigger();
|
||||
}
|
||||
template <class Result> Result QueueCommand(CommandWithResult <Result> *c)
|
||||
{
|
||||
QueueCommand((Command *)c);
|
||||
|
||||
Result result = c->future_result.Get(); // wait for command result
|
||||
c->dispose.Set(1); // flag command disposal
|
||||
return result; // return result
|
||||
}
|
||||
|
||||
bool Start()
|
||||
{ return worker.Start(); }
|
||||
void Stop()
|
||||
{ worker.Stop(); }
|
||||
|
||||
Controller(Target *t) : worker(t) {}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __THREAD_CONTROLLER__
|
||||
Reference in New Issue
Block a user