202 lines
8.3 KiB
C++
202 lines
8.3 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#ifndef __ASYNC_CALL_QUEUE__
|
|
#define __ASYNC_CALL_QUEUE__
|
|
|
|
|
|
#include "async/future.h"
|
|
#include "thread/thread.h"
|
|
#include "thread/mutex.h"
|
|
#include "container/nlist.h"
|
|
|
|
|
|
namespace GS {
|
|
namespace ASync {
|
|
|
|
/*!
|
|
@short Asynchronous call queue.
|
|
@author Emmanuel Julien (ejulien@owloh.com)
|
|
*/
|
|
class CallQueue
|
|
{
|
|
struct BaseCall
|
|
{
|
|
virtual void Execute() = 0;
|
|
virtual ~BaseCall() {}
|
|
};
|
|
|
|
Threading::Mutex queue_mutex;
|
|
List <BaseCall *> call_queue;
|
|
|
|
/// Post a call to the queue.
|
|
void Queue(BaseCall *m)
|
|
{
|
|
Threading::MutexLock lock(&queue_mutex);
|
|
call_queue.Append(m);
|
|
}
|
|
|
|
private:
|
|
|
|
// Call a member function, ignore the return value.
|
|
template <typename I, typename F> struct MemberCall : public BaseCall
|
|
{
|
|
I i; F fn;
|
|
void Execute() { (i->*fn)(); }
|
|
MemberCall(I _i, F _fn) : i(_i), fn(_fn) {}
|
|
};
|
|
template <typename I, typename F, typename A1> struct MemberCall1 : public BaseCall
|
|
{
|
|
I i; F fn; A1 a1;
|
|
void Execute() { (i->*fn)(a1); }
|
|
MemberCall1(I _i, F _fn, const A1 &_a1) : i(_i), fn(_fn), a1(_a1) {}
|
|
};
|
|
template <typename I, typename F, typename A1, typename A2> struct MemberCall2 : public BaseCall
|
|
{
|
|
I i; F fn; A1 a1; A2 a2;
|
|
void Execute() { (i->*fn)(a1, a2); }
|
|
MemberCall2(I _i, F _fn, const A1 &_a1, const A2 &_a2) : i(_i), fn(_fn), a1(_a1), a2(_a2) {}
|
|
};
|
|
template <typename I, typename F, typename A1, typename A2, typename A3> struct MemberCall3 : public BaseCall
|
|
{
|
|
I i; F fn; A1 a1; A2 a2; A3 a3;
|
|
void Execute() { (i->*fn)(a1, a2, a3); }
|
|
MemberCall3(I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3) : i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3) {}
|
|
};
|
|
template <typename I, typename F, typename A1, typename A2, typename A3, typename A4> struct MemberCall4 : public BaseCall
|
|
{
|
|
I i; F fn; A1 a1; A2 a2; A3 a3; A4 a4;
|
|
void Execute() { (i->*fn)(a1, a2, a3, a4); }
|
|
MemberCall4(I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3, const A4 &_a4) : i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3), a4(_a4) {}
|
|
};
|
|
|
|
public:
|
|
|
|
template <typename I, typename F> void QueueMemberCall(I i, F fn)
|
|
{ Queue(new MemberCall <I, F> (i, fn)); }
|
|
template <typename I, typename F, typename A1> void QueueMemberCall(I i, F fn, const A1 &a1)
|
|
{ Queue(new MemberCall1 <I, F, A1> (i, fn, a1)); }
|
|
template <typename I, typename F, typename A1, typename A2> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2)
|
|
{ Queue(new MemberCall2 <I, F, A1, A2> (i, fn, a1, a2)); }
|
|
template <typename I, typename F, typename A1, typename A2, typename A3> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3)
|
|
{ Queue(new MemberCall3 <I, F, A1, A2, A3> (i, fn, a1, a2, a3)); }
|
|
template <typename I, typename F, typename A1, typename A2, typename A3, typename A4> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
|
|
{ Queue(new MemberCall4 <I, F, A1, A2, A3, A4> (i, fn, a1, a2, a3, a4)); }
|
|
|
|
private:
|
|
|
|
// Generic return value calls.
|
|
template <typename R, typename I, typename F> struct RValMemberCall : public BaseCall
|
|
{
|
|
Future <R> &future; I i; F fn;
|
|
void Execute() { future.Set((i->*fn)()); }
|
|
RValMemberCall(Future <R> &_future, I _i, F _fn) : future(_future), i(_i), fn(_fn) {}
|
|
};
|
|
template <typename R, typename I, typename F, typename A1> struct RValMemberCall1 : public BaseCall
|
|
{
|
|
Future <R> &future; I i; F fn; A1 a1;
|
|
void Execute() { future.Set((i->*fn)(a1)); }
|
|
RValMemberCall1(Future <R> &_future, I _i, F _fn, const A1 &_a1) : future(_future), i(_i), fn(_fn), a1(_a1) {}
|
|
};
|
|
template <typename R, typename I, typename F, typename A1, typename A2> struct RValMemberCall2 : public BaseCall
|
|
{
|
|
Future <R> &future; I i; F fn; A1 a1; A2 a2;
|
|
void Execute() { future.Set((i->*fn)(a1, a2)); }
|
|
RValMemberCall2(Future <R> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2) {}
|
|
};
|
|
template <typename R, typename I, typename F, typename A1, typename A2, typename A3> struct RValMemberCall3 : public BaseCall
|
|
{
|
|
Future <R> &future; I i; F fn; A1 a1; A2 a2; A3 a3;
|
|
void Execute() { future.Set((i->*fn)(a1, a2, a3)); }
|
|
RValMemberCall3(Future <R> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3) {}
|
|
};
|
|
template <typename R, typename I, typename F, typename A1, typename A2, typename A3, typename A4> struct RValMemberCall4 : public BaseCall
|
|
{
|
|
Future <R> &future; I i; F fn; A1 a1; A2 a2; A3 a3; A4 a4;
|
|
void Execute() { future.Set((i->*fn)(a1, a2, a3, a4)); }
|
|
RValMemberCall4(Future <R> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3, const A4 &_a4) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3), a4(_a4) {}
|
|
};
|
|
|
|
// No return value specialized calls.
|
|
template <typename I, typename F> struct RValMemberCall <void, I, F> : public BaseCall
|
|
{
|
|
Future <void> &future; I i; F fn;
|
|
void Execute() { (i->*fn)(); future.Set(); }
|
|
RValMemberCall(Future <void> &_future, I _i, F _fn) : future(_future), i(_i), fn(_fn) {}
|
|
};
|
|
template <typename I, typename F, typename A1> struct RValMemberCall1 <void, I, F, A1> : public BaseCall
|
|
{
|
|
Future <void> &future; I i; F fn; A1 a1;
|
|
void Execute() { (i->*fn)(a1); future.Set(); }
|
|
RValMemberCall1(Future <void> &_future, I _i, F _fn, const A1 &_a1) : future(_future), i(_i), fn(_fn), a1(_a1) {}
|
|
};
|
|
template <typename I, typename F, typename A1, typename A2> struct RValMemberCall2 <void, I, F, A1, A2> : public BaseCall
|
|
{
|
|
Future <void> &future; I i; F fn; A1 a1; A2 a2;
|
|
void Execute() { (i->*fn)(a1, a2); future.Set(); }
|
|
RValMemberCall2(Future <void> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2) {}
|
|
};
|
|
template <typename I, typename F, typename A1, typename A2, typename A3> struct RValMemberCall3 <void, I, F, A1, A2, A3> : public BaseCall
|
|
{
|
|
Future <void> &future; I i; F fn; A1 a1; A2 a2; A3 a3;
|
|
void Execute() { (i->*fn)(a1, a2, a3); future.Set(); }
|
|
RValMemberCall3(Future <void> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3) {}
|
|
};
|
|
template <typename I, typename F, typename A1, typename A2, typename A3, typename A4> struct RValMemberCall4 <void, I, F, A1, A2, A3, A4> : public BaseCall
|
|
{
|
|
Future <void> &future; I i; F fn; A1 a1; A2 a2; A3 a3; A4 a4;
|
|
void Execute() { (i->*fn)(a1, a2, a3, a4); future.Set(); }
|
|
RValMemberCall4(Future <void> &_future, I _i, F _fn, const A1 &_a1, const A2 &_a2, const A3 &_a3, const A4 &_a4) : future(_future), i(_i), fn(_fn), a1(_a1), a2(_a2), a3(_a3), a4(_a4) {}
|
|
};
|
|
|
|
public:
|
|
|
|
/// Queue a member call, return the value in a future.
|
|
template <typename R, typename I, typename F> void QueueMemberCall(Future <R> &f, I i, F fn)
|
|
{ Queue(new RValMemberCall <R, I, F> (f, i, fn)); }
|
|
template <typename R, typename I, typename F, typename A1> void QueueMemberCall(Future <R> &f, I i, F fn, const A1 &a1)
|
|
{ Queue(new RValMemberCall1 <R, I, F, A1> (f, i, fn, a1)); }
|
|
template <typename R, typename I, typename F, typename A1, typename A2> void QueueMemberCall(Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2)
|
|
{ Queue(new RValMemberCall2 <R, I, F, A1, A2> (f, i, fn, a1, a2)); }
|
|
template <typename R, typename I, typename F, typename A1, typename A2, typename A3> void QueueMemberCall(Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3)
|
|
{ Queue(new RValMemberCall3 <R, I, F, A1, A2, A3> (f, i, fn, a1, a2, a3)); }
|
|
template <typename R, typename I, typename F, typename A1, typename A2, typename A3, typename A4> void QueueMemberCall(Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
|
|
{ Queue(new RValMemberCall4 <R, I, F, A1, A2, A3, A4> (f, i, fn, a1, a2, a3, a4)); }
|
|
|
|
public:
|
|
|
|
bool Execute()
|
|
{
|
|
BaseCall *c = NULL;
|
|
{
|
|
Threading::MutexLock lock(&queue_mutex);
|
|
|
|
if (call_queue.GetCount() == 0)
|
|
return false;
|
|
|
|
c = call_queue[0];
|
|
call_queue.RemoveAt(0);
|
|
}
|
|
|
|
if (c)
|
|
{
|
|
c->Execute();
|
|
delete c;
|
|
}
|
|
return asbool(c);
|
|
}
|
|
void ExecuteAll()
|
|
{
|
|
while (Execute() == true) {}
|
|
}
|
|
};
|
|
|
|
} // ASync
|
|
} // GS
|
|
|
|
|
|
#endif // __ASYNC_CALL_QUEUE__
|