00001 #ifndef INC_GAM_SCHEDULER_H
00002 #define INC_GAM_SCHEDULER_H
00003
00004 #include "Gamma/Node.h"
00005 #include "Gamma/AudioIO.h"
00006 #include "Gamma/Thread.h"
00007 #include "Gamma/Timer.h"
00008 #include <queue>
00009 #include <list>
00010
00011 namespace gam{
00012
00013 class Scheduler;
00014
00015
00016 #ifndef FUNC_MAX_DATA_SIZE
00017 #define FUNC_MAX_DATA_SIZE 64
00018 #endif
00019
00021 class Func{
00022 public:
00023 typedef void (* func_t)(void * data);
00024
00025 template <class R>
00026 Func(R (*fnc)()){
00027 struct Data{
00028 R (*fnc)();
00029 static void call(void * data){
00030 Data& d = *(Data *)data;
00031 d.fnc();
00032 }
00033 } data = {fnc};
00034 set(Data::call, (void *)&data, sizeof(Data));
00035 }
00036
00037 template <class R, class A, class L>
00038 Func(R (*fnc)(A), L l){
00039 struct Data{
00040 R (*fnc)(A);
00041 L l;
00042 static void call(void * data){
00043 Data& d = *(Data *)data;
00044 d.fnc(d.l);
00045 }
00046 } data = {fnc,l};
00047 set(Data::call, (void *)&data, sizeof(Data));
00048 }
00049
00050 template <class R, class A, class B, class L, class M>
00051 Func(R (*fnc)(A,B), L l, M m){
00052 struct Data{
00053 R (*fnc)(A,B);
00054 L l; M m;
00055 static void call(void * data){
00056 Data& d = *(Data *)data;
00057 d.fnc(d.l,d.m);
00058 }
00059 } data = {fnc,l,m};
00060 set(Data::call, (void *)&data, sizeof(Data));
00061 }
00062
00063 template <class R, class A, class B, class C, class L, class M, class N>
00064 Func(R (*fnc)(A,B,C), L l, M m, N n){
00065 struct Data{
00066 R (*fnc)(A,B,C);
00067 L l; M m; N n;
00068 static void call(void * data){
00069 Data& d = *(Data *)data;
00070 d.fnc(d.l,d.m,d.n);
00071 }
00072 } data = {fnc,l,m,n};
00073 set(Data::call, (void *)&data, sizeof(Data));
00074 }
00075
00076 template <class R, class A, class B, class C, class D, class L, class M, class N, class O>
00077 Func(R (*fnc)(A,B,C,D), L l, M m, N n, O o){
00078 struct Data{
00079 R (*fnc)(A,B,C,D);
00080 L l; M m; N n; O o;
00081 static void call(void * data){
00082 Data& d = *(Data *)data;
00083 d.fnc(d.l,d.m,d.n,d.o);
00084 }
00085 } data = {fnc,l,m,n,o};
00086 set(Data::call, (void *)&data, sizeof(Data));
00087 }
00088
00089
00090 template <class Obj1, class Obj2, class R>
00091 Func(Obj1& obj, R (Obj2::*mth)()){
00092 struct Data{
00093 Obj1& obj;
00094 R (Obj2::*mth)();
00095 static void call(void * data){
00096 Data& d = *(Data *)data;
00097 (d.obj.*d.mth)();
00098 }
00099 } data = {obj,mth};
00100 set(Data::call, (void *)&data, sizeof(Data));
00101 }
00102
00103 template <class Obj1, class Obj2, class R, class A, class L>
00104 Func(Obj1& obj, R (Obj2::*mth)(A), L l){
00105 struct Data{
00106 Obj1& obj;
00107 R (Obj2::*mth)(A);
00108 L l;
00109 static void call(void * data){
00110 Data& d = *(Data *)data;
00111 (d.obj.*d.mth)(d.l);
00112 }
00113 } data = {obj,mth,l};
00114 set(Data::call, (void *)&data, sizeof(Data));
00115 }
00116
00117 template <class Obj1, class Obj2, class R, class A, class B, class L, class M>
00118 Func(Obj1& obj, R (Obj2::*mth)(A,B), L l, M m){
00119 struct Data{
00120 Obj1& obj;
00121 R (Obj2::*mth)(A,B);
00122 L l; M m;
00123 static void call(void * data){
00124 Data& d = *(Data *)data;
00125 (d.obj.*d.mth)(d.l,d.m);
00126 }
00127 } data = {obj,mth,l,m};
00128 set(Data::call, (void *)&data, sizeof(Data));
00129 }
00130
00131 template <class Obj1, class Obj2, class R, class A, class B, class C, class L, class M, class N>
00132 Func(Obj1& obj, R (Obj2::*mth)(A,B,C), L l, M m, N n){
00133 struct Data{
00134 Obj1& obj;
00135 R (Obj2::*mth)(A,B,C);
00136 L l; M m; N n;
00137 static void call(void * data){
00138 Data& d = *(Data *)data;
00139 (d.obj.*d.mth)(d.l,d.m,d.n);
00140 }
00141 } data = {obj,mth,l,m,n};
00142 set(Data::call, (void *)&data, sizeof(Data));
00143 }
00144
00145 template <class Obj1, class Obj2, class R, class A, class B, class C, class D, class L, class M, class N, class O>
00146 Func(Obj1& obj, R (Obj2::*mth)(A,B,C,D), L l, M m, N n, O o){
00147 struct Data{
00148 Obj1& obj;
00149 R (Obj2::*mth)(A,B,C,D);
00150 L l; M m; N n; O o;
00151 static void call(void * data){
00152 Data& d = *(Data *)data;
00153 (d.obj.*d.mth)(d.l,d.m,d.n,d.o);
00154 }
00155 } data = {obj,mth,l,m,n,o};
00156 set(Data::call, (void *)&data, sizeof(Data));
00157 }
00158
00160 void operator()(){ mFunc(mData); }
00161
00162 const char * data() const { return mData; }
00163 const void * obj() const { return mObj; }
00164
00165 private:
00166 union{
00167 char mData[FUNC_MAX_DATA_SIZE];
00168 void * mObj;
00169 };
00170 func_t mFunc;
00171
00172 void set(func_t f, void * data, int size){
00173 mFunc = f;
00174 #ifndef NDEBUG
00175 if(size > FUNC_MAX_DATA_SIZE){
00176 printf("Func maximum data size exceeded. "
00177 "Attempt to use %d bytes with maximum size set to %d.\n",
00178 size, FUNC_MAX_DATA_SIZE);
00179 exit(-1);
00180 }
00181 #endif
00182 memcpy(mData, data, size);
00183
00184 }
00185 };
00186
00187
00188
00189
00190 class Process : public Node3<Process>{
00191 public:
00192
00193 Process(double delay=0.);
00194
00195 virtual ~Process();
00196
00198 Process& dt(double v){ mDelay=v; return *this; }
00199
00201 Process& free();
00202
00204
00207 Process& active(bool v);
00208
00209 Process& reset();
00210
00212 Process * update(const Process * top, AudioIOData& io);
00213
00214 bool deletable() const { return mDeletable; }
00215 bool done() const { return DONE==mStatus; }
00216 bool active() const { return ACTIVE==mStatus; }
00217 bool inactive() const { return INACTIVE==mStatus; }
00218
00219 void print();
00220
00221 protected:
00222 friend class Scheduler;
00223
00224 enum{
00225 INACTIVE=0,
00226 ACTIVE,
00227 DONE
00228 };
00229
00230 int mStatus;
00231 double mDelay;
00232 bool mDeletable;
00233
00234 virtual void onProcess(AudioIOData& io){}
00235 virtual void onReset(){}
00236
00237 Process * process(const Process * top, AudioIOData& io, int frameStart=0);
00238 };
00239
00240
00241
00242 class ControlFunc{
00243 public:
00244 ControlFunc(const Func& f, double dt=0)
00245 : mFunc(f), mDelay(dt), mPeriod(0), mObjDel(0)
00246 {}
00247
00248 ControlFunc& dt(double v){ mDelay=v; return *this; }
00249 ControlFunc& period(double v){ mPeriod=v; return *this; }
00250
00251 void operator()(){ mFunc(); }
00252
00253 protected:
00254 friend class Scheduler;
00255 Func mFunc;
00256 double mDelay;
00257 double mPeriod;
00258 int mObjDel;
00259 };
00260
00261
00262
00263 class Scheduler : public Process{
00264 public:
00265
00266 typedef std::queue<Process *> FreeList;
00267 typedef std::list<ControlFunc> Funcs;
00268
00269 Scheduler();
00270
00271 ~Scheduler();
00272
00274 bool empty() const;
00275
00277 bool check();
00278
00280
00283 int reclaim();
00284
00286 template <class AProcess>
00287 AProcess& add(){
00288 AProcess * v = new AProcess;
00289 cmdAdd(v); return *v;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 template <class AProcess, class A>
00302 AProcess& add(const A& a){
00303 AProcess * v = new AProcess(a);
00304 cmdAdd(v); return *v;
00305 }
00306
00307 template <class AProcess, class A, class B>
00308 AProcess& add(const A& a, const B& b){
00309 AProcess * v = new AProcess(a,b);
00310 cmdAdd(v); return *v;
00311 }
00312
00313 template <class AProcess, class A, class B, class C>
00314 AProcess& add(const A& a, const B& b, const C& c){
00315 AProcess * v = new AProcess(a,b,c);
00316 cmdAdd(v); return *v;
00317 }
00318
00319 template <class AProcess, class A, class B, class C, class D>
00320 AProcess& add(const A& a, const B& b, const C& c, const D& d){
00321 AProcess * v = new AProcess(a,b,c,d);
00322 cmdAdd(v); return *v;
00323 }
00324
00325 template <class AProcess, class A, class B, class C, class D, class E>
00326 AProcess& add(const A& a, const B& b, const C& c, const D& d, const E& e){
00327 AProcess * v = new AProcess(a,b,c,d,e);
00328 cmdAdd(v); return *v;
00329 }
00330
00331 template <class AProcess, class A, class B, class C, class D, class E, class F>
00332 AProcess& add(const A& a, const B& b, const C& c, const D& d, const E& e, const F& f){
00333 AProcess * v = new AProcess(a,b,c,d,e,f);
00334 cmdAdd(v); return *v;
00335 }
00336
00337
00339 template <class AProcess>
00340 AProcess& add(Process& parent){
00341 AProcess * v = new AProcess;
00342 pushCommand(Command::ADD_FIRST_CHILD, &parent, v);
00343 return *v;
00344 }
00345
00346
00347
00348 ControlFunc& add(const Func& f){
00349 mFuncs.push_back(f);
00350 return mFuncs.back();
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00369
00372 void update(AudioIOData& io);
00373
00374 Scheduler& period(float v);
00375
00376 void start();
00377
00378 void stop();
00379
00380 static void audioCB(AudioIOData& io){
00381 Scheduler& s = io.user<Scheduler>();
00382 s.update(io);
00383 }
00384
00385 protected:
00386
00387 struct Command{
00388 enum Type{
00389 ADD_FIRST_CHILD,
00390 ADD_LAST_CHILD,
00391 REMOVE_CHILD
00392 };
00393
00394 Type type;
00395 Process * object;
00396 Process * other;
00397 };
00398
00399
00400
00401 std::queue<Command> mAddCommands;
00402 FreeList mFreeList;
00403 Funcs mFuncs;
00404 Thread mThread;
00405 float mPeriod;
00406 double mTime;
00407 bool mRunning;
00408
00409 static void * cThreadFunc(void * user);
00410
00411 void updateControlFuncs(double dt);
00412
00413 void pushCommand(Command::Type c, Process * object, Process * other);
00414 void cmdAdd(Process * v);
00415
00416
00417
00418
00419 void updateTree();
00420
00421
00422
00423 void updateFreeList();
00424 };
00425
00426 }
00427
00428 #endif