first commit
This commit is contained in:
201
include/platform/async/async_call_queue.h
Normal file
201
include/platform/async/async_call_queue.h
Normal file
@ -0,0 +1,201 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
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__
|
||||
84
include/platform/async/async_call_queue_thread.h
Normal file
84
include/platform/async/async_call_queue_thread.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __ASYNC_CALL_QUEUE_THREAD__
|
||||
#define __ASYNC_CALL_QUEUE_THREAD__
|
||||
|
||||
|
||||
#include "async/async_call_queue.h"
|
||||
#include "thread/thread_event.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace Threading {
|
||||
|
||||
/*!
|
||||
@short A worker thread whose sole purpose is to process its async call queue.
|
||||
@author Emmanuel Julien (ejulien@owloh.com)
|
||||
*/
|
||||
class ASyncCallQueueThread : public Thread
|
||||
{
|
||||
Atomic32 acqt_running;
|
||||
Event queue_event;
|
||||
|
||||
ASync::CallQueue call_queue;
|
||||
|
||||
public:
|
||||
|
||||
virtual void OnIdle() {}
|
||||
|
||||
virtual void Execute()
|
||||
{
|
||||
for (acqt_running.Set(1); acqt_running.Get() != 2; )
|
||||
{
|
||||
call_queue.ExecuteAll();
|
||||
OnIdle();
|
||||
queue_event.Wait();
|
||||
}
|
||||
acqt_running.Set(0);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (acqt_running.Get() != 0)
|
||||
{
|
||||
acqt_running.Set(2);
|
||||
queue_event.Trigger();
|
||||
while (acqt_running.Get() != 0); // spinlock
|
||||
}
|
||||
}
|
||||
|
||||
template <typename I, typename F> void QueueMemberCall(I i, F fn)
|
||||
{ call_queue.QueueMemberCall(i, fn); queue_event.Trigger(); }
|
||||
template <typename I, typename F, typename A1> void QueueMemberCall(I i, F fn, const A1 &a1)
|
||||
{ call_queue.QueueMemberCall(i, fn, a1); queue_event.Trigger(); }
|
||||
template <typename I, typename F, typename A1, typename A2> void QueueMemberCall(I i, F fn, const A1 &a1, const A2 &a2)
|
||||
{ call_queue.QueueMemberCall(i, fn, a1, a2); queue_event.Trigger(); }
|
||||
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)
|
||||
{ call_queue.QueueMemberCall(i, fn, a1, a2, a3); queue_event.Trigger(); }
|
||||
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)
|
||||
{ call_queue.QueueMemberCall(i, fn, a1, a2, a3, a4); queue_event.Trigger(); }
|
||||
|
||||
/// Queue a member call, return the value in a future.
|
||||
template <typename R, typename I, typename F> void QueueMemberCall(ASync::Future <R> &f, I i, F fn)
|
||||
{ call_queue.QueueMemberCall(f, i, fn); queue_event.Trigger(); }
|
||||
template <typename R, typename I, typename F, typename A1> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1)
|
||||
{ call_queue.QueueMemberCall(f, i, fn, a1); queue_event.Trigger(); }
|
||||
template <typename R, typename I, typename F, typename A1, typename A2> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2)
|
||||
{ call_queue.QueueMemberCall(f, i, fn, a1, a2); queue_event.Trigger(); }
|
||||
template <typename R, typename I, typename F, typename A1, typename A2, typename A3> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3)
|
||||
{ call_queue.QueueMemberCall(f, i, fn, a1, a2, a3); queue_event.Trigger(); }
|
||||
template <typename R, typename I, typename F, typename A1, typename A2, typename A3, typename A4> void QueueMemberCall(ASync::Future <R> &f, I i, F fn, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
|
||||
{ call_queue.QueueMemberCall(f, i, fn, a1, a2, a3, a4); queue_event.Trigger(); }
|
||||
|
||||
virtual ~ASyncCallQueueThread()
|
||||
{ Stop(); }
|
||||
};
|
||||
|
||||
} // Threading
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __ASYNC_CALL_QUEUE_THREAD__
|
||||
67
include/platform/async/future.h
Normal file
67
include/platform/async/future.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NFUTURE__
|
||||
#define __NFUTURE__
|
||||
|
||||
|
||||
#include "thread/atomic_value.h"
|
||||
#include "memory/nshared_ptr.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace ASync {
|
||||
|
||||
/*
|
||||
@short Future.
|
||||
@author Emmanuel Julien (ejulien@nworks.fr)
|
||||
*/
|
||||
template <class T> class Future
|
||||
{
|
||||
T value;
|
||||
Threading::Atomic32 set;
|
||||
|
||||
public:
|
||||
|
||||
bool IsSet() const
|
||||
{ return set.Get() == 1; }
|
||||
void Set(const T &_value)
|
||||
{
|
||||
value = _value;
|
||||
set.Set(1);
|
||||
}
|
||||
|
||||
void Wait()
|
||||
{ while (!IsSet()); }
|
||||
|
||||
T &Get()
|
||||
{
|
||||
Wait();
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
template <> class Future <void>
|
||||
{
|
||||
Threading::Atomic32 set;
|
||||
|
||||
public:
|
||||
|
||||
bool IsSet() const
|
||||
{ return set.Get() == 1; }
|
||||
void Set()
|
||||
{ set.Set(1); }
|
||||
|
||||
void Wait()
|
||||
{ while (!IsSet()); }
|
||||
};
|
||||
|
||||
} // ASync
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __NFUTURE__
|
||||
131
include/platform/async/job.h
Normal file
131
include/platform/async/job.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __JOB_SYSTEM__
|
||||
#define __JOB_SYSTEM__
|
||||
|
||||
|
||||
#define __USE_LOCK_FREE_JOB_QUEUE__ 1
|
||||
|
||||
#include "thread/thread_event.h"
|
||||
#include "thread/thread.h"
|
||||
#include "thread/mutex.h"
|
||||
#include "container/nlist.h"
|
||||
#if __USE_LOCK_FREE_JOB_QUEUE__
|
||||
#include "container/mpmc_bounded_queue.h"
|
||||
#else
|
||||
#include "container/nstack.h"
|
||||
#endif
|
||||
#include "container/narray.h"
|
||||
#include "memory/nauto_ptr.h"
|
||||
#include "nstring/nstring.h"
|
||||
#include "time/ntime.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace ASync {
|
||||
class JobManager;
|
||||
|
||||
//
|
||||
class JobWorkerThread : public Threading::Thread
|
||||
{
|
||||
protected:
|
||||
|
||||
JobManager &manager;
|
||||
|
||||
Threading::Atomic32 running;
|
||||
uint worker_id;
|
||||
|
||||
public:
|
||||
|
||||
/// Get worker id.
|
||||
int GetWorkerId() const { return worker_id; }
|
||||
/// Worker loop.
|
||||
virtual void Execute();
|
||||
|
||||
/// Stop worker thread.
|
||||
void Stop();
|
||||
/// Is the worker thread running.
|
||||
bool IsRunning() const;
|
||||
|
||||
JobWorkerThread(JobManager &m, uint id) : manager(m), worker_id(id) {}
|
||||
};
|
||||
|
||||
/// Parallel job.
|
||||
struct Job
|
||||
{
|
||||
String name;
|
||||
Time time_start, time_end;
|
||||
|
||||
Threading::Atomic32 done;
|
||||
|
||||
/// Execute job.
|
||||
virtual void Execute(uint worker_id) = 0;
|
||||
|
||||
Job(const char *_name) : name(_name), done(1) {}
|
||||
virtual ~Job() {}
|
||||
};
|
||||
|
||||
/// Job group.
|
||||
class JobGroup
|
||||
{
|
||||
friend class JobManager;
|
||||
|
||||
AutoPtr <Threading::Mutex> job_list_mutex;
|
||||
List <Job *> job_list;
|
||||
|
||||
public:
|
||||
|
||||
JobGroup();
|
||||
};
|
||||
|
||||
//
|
||||
class JobManager
|
||||
{
|
||||
friend class JobWorkerThread;
|
||||
|
||||
protected:
|
||||
|
||||
Array <JobWorkerThread *> pool;
|
||||
|
||||
#if __USE_LOCK_FREE_JOB_QUEUE__
|
||||
mpmc_bounded_queue <Job *> pending_queue;
|
||||
#else
|
||||
AutoPtr <Mutex> pending_queue_mutex;
|
||||
Stack <Job *> pending_queue;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
Threading::Event job_queued_event;
|
||||
|
||||
/// Wait for a job to complete.
|
||||
bool JoinJob(Job *, bool blocking = true);
|
||||
/// Wait for a job group to complete.
|
||||
bool JoinGroup(JobGroup *, bool blocking = true);
|
||||
|
||||
/// Execute a pending job on the caller thread.
|
||||
bool ExecutePendingJob(uint worker_id);
|
||||
|
||||
bool EnqueueJob(Job * = 0, JobGroup * = 0);
|
||||
|
||||
/// Get the number of worker.
|
||||
uint GetWorkerPoolSize() const;
|
||||
|
||||
/// Create the job worker thread pool.
|
||||
bool CreateJobThreadPool(uint count = 0);
|
||||
/// Free the job worker thread pool.
|
||||
void FreeJobThreadPool();
|
||||
|
||||
JobManager();
|
||||
~JobManager();
|
||||
};
|
||||
|
||||
} // ASync
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __JOB_SYSTEM__
|
||||
55
include/platform/async/job_perf.h
Normal file
55
include/platform/async/job_perf.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __JOB_PERF__
|
||||
#define __JOB_PERF__
|
||||
|
||||
|
||||
#include "async/job.h"
|
||||
|
||||
|
||||
namespace GS {
|
||||
namespace ASync {
|
||||
|
||||
//
|
||||
struct JobPerf
|
||||
{
|
||||
Time slice_duration;
|
||||
Time tasks_duration;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
slice_duration.setSec(0);
|
||||
tasks_duration.setSec(0);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
template <class Container> void CollectJobsPerf(const Container &jobs, uint count, JobPerf &perf)
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
|
||||
Time slice_start = jobs[0]->time_start, slice_end = jobs[0]->time_end;
|
||||
|
||||
perf.tasks_duration += jobs[0]->time_end - jobs[0]->time_start;
|
||||
|
||||
for (uint n = 1; n < count; ++n)
|
||||
{
|
||||
slice_start = Types::Min(jobs[n]->time_start, slice_start);
|
||||
slice_end = Types::Max(jobs[n]->time_end, slice_end);
|
||||
|
||||
perf.tasks_duration += jobs[n]->time_end - jobs[n]->time_start;
|
||||
}
|
||||
|
||||
perf.slice_duration += slice_end - slice_start;
|
||||
};
|
||||
|
||||
} // ASync
|
||||
} // GS
|
||||
|
||||
|
||||
#endif // __JOB_PERF__
|
||||
40
include/platform/async/task_loop.h
Normal file
40
include/platform/async/task_loop.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef __NTASKLOOP__
|
||||
#define __NTASKLOOP__
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#define StartTaskLoop(_CONDITION, _TIMEOUT)\
|
||||
{\
|
||||
using namespace GS;\
|
||||
\
|
||||
int ref_clock = Platform::Get().GetClock();\
|
||||
bool timeout = false;\
|
||||
\
|
||||
while (_CONDITION)\
|
||||
{\
|
||||
if ((Platform::Get().GetClock() - ref_clock) >= _TIMEOUT)\
|
||||
{\
|
||||
timeout = true;\
|
||||
break;\
|
||||
}
|
||||
|
||||
#define EndTaskLoop } }
|
||||
|
||||
#define EndTaskLoopOnTimeout(_ON_TIMEOUT)\
|
||||
}\
|
||||
\
|
||||
if (timeout)\
|
||||
{\
|
||||
_ON_TIMEOUT\
|
||||
}\
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#endif // __NTASKLOOP__
|
||||
Reference in New Issue
Block a user