Files
Webcam/include/platform/thread/thread_controller.h
2026-06-22 11:49:35 +02:00

136 lines
2.9 KiB
C++

/* -----------------------------------------------------------------------------
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__