first commit
This commit is contained in:
49
include/platform/thread/atomic_value.h
Normal file
49
include/platform/thread/atomic_value.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __ATOMIC_VALUE__
|
||||
#define __ATOMIC_VALUE__
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
/*!
|
||||
@short 32bit atomic value.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
class Atomic32
|
||||
{
|
||||
void *v;
|
||||
|
||||
public:
|
||||
|
||||
/// Perform atomic increment, return the new value.
|
||||
int Inc();
|
||||
/// Perform atomic decrement, return the new value.
|
||||
int Dec();
|
||||
|
||||
/// Return the current value.
|
||||
int Get() const;
|
||||
/// Set new value, return the initial value.
|
||||
int Set(int);
|
||||
|
||||
/*!
|
||||
@short Perform an atomic compare and swap operation.
|
||||
Compare the current value with the comparand, if they match set the
|
||||
new value. Return the initial value.
|
||||
*/
|
||||
int Cas(int comparand, int value);
|
||||
|
||||
explicit Atomic32(int value = 0);
|
||||
~Atomic32();
|
||||
};
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __ATOMIC_VALUE__
|
||||
90
include/platform/thread/mutex.h
Normal file
90
include/platform/thread/mutex.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NMUTEX__
|
||||
#define __NMUTEX__
|
||||
|
||||
|
||||
#if __PLATFORM_POSIX__
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#elif __PLATFORM_NINTENDO_WII__
|
||||
#include <revolution.h>
|
||||
#endif
|
||||
#include "ntypes.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
/// Portable mutex class.
|
||||
class Mutex
|
||||
{
|
||||
protected:
|
||||
|
||||
#if __PLATFORM_POSIX__
|
||||
pthread_mutex_t mutex;
|
||||
#elif __PLATFORM_WINDOWS__
|
||||
void *mutex;
|
||||
#elif __PLATFORM_NINTENDO_WII__
|
||||
OSMutex mutex;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
|
||||
Mutex();
|
||||
~Mutex();
|
||||
};
|
||||
|
||||
/// Mutex helper class.
|
||||
class MutexLock
|
||||
{
|
||||
protected:
|
||||
|
||||
Mutex *mutex;
|
||||
|
||||
public:
|
||||
|
||||
bool HasLock() const
|
||||
{ return asbool(mutex); }
|
||||
|
||||
void Lock(Mutex *m, bool try_only)
|
||||
{
|
||||
Unlock();
|
||||
|
||||
if (try_only)
|
||||
{
|
||||
if (m && m->TryLock())
|
||||
mutex = m;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m)
|
||||
(mutex = m)->Lock();
|
||||
}
|
||||
}
|
||||
void Unlock()
|
||||
{
|
||||
if (mutex)
|
||||
mutex->Unlock();
|
||||
mutex = 0;
|
||||
}
|
||||
|
||||
MutexLock(Mutex *m, bool try_only = false) : mutex(0)
|
||||
{ Lock(m, try_only); }
|
||||
~MutexLock()
|
||||
{ Unlock(); }
|
||||
};
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NMUTEX__
|
||||
55
include/platform/thread/thread.h
Normal file
55
include/platform/thread/thread.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NTHREAD__
|
||||
#define __NTHREAD__
|
||||
|
||||
|
||||
#include "thread/atomic_value.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
/*
|
||||
@short Thread abstraction class.
|
||||
@author Emmanuel Julien (ejulien@gsworks.fr)
|
||||
*/
|
||||
struct Thread
|
||||
{
|
||||
void *handle;
|
||||
|
||||
virtual bool Start();
|
||||
|
||||
void Kill();
|
||||
void Join();
|
||||
|
||||
static void SetName(const char *);
|
||||
// Yield execution to the next running system thread.
|
||||
static void Switch();
|
||||
|
||||
/*
|
||||
@short Set thread priority.
|
||||
|
||||
Set the thread priority from 0 to 31.
|
||||
0 is the highest priority, 31 is the lowest.
|
||||
|
||||
@return False is the required priority was invalid.
|
||||
*/
|
||||
bool SetPriority(int priority = 16);
|
||||
|
||||
/// Main thread execution function.
|
||||
virtual void Execute() = 0;
|
||||
|
||||
Thread();
|
||||
virtual ~Thread();
|
||||
};
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NTHREAD__
|
||||
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__
|
||||
38
include/platform/thread/thread_event.h
Normal file
38
include/platform/thread/thread_event.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NTHREAD_EVENT__
|
||||
#define __NTHREAD_EVENT__
|
||||
|
||||
|
||||
#include "time/ntime.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
/*!
|
||||
@short Multi-threaded event.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
struct Event
|
||||
{
|
||||
void *event;
|
||||
|
||||
/// Thread entering this function will suspend until this event is triggered.
|
||||
void Wait(Time * = 0);
|
||||
/// Trigger event.
|
||||
void Trigger();
|
||||
|
||||
Event();
|
||||
~Event();
|
||||
};
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NTHREAD_EVENT__
|
||||
Reference in New Issue
Block a user