command_queue_mt.h
1 /*************************************************************************/
2 /* command_queue_mt.h */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* http://www.godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
9 /* */
10 /* Permission is hereby granted, free of charge, to any person obtaining */
11 /* a copy of this software and associated documentation files (the */
12 /* "Software"), to deal in the Software without restriction, including */
13 /* without limitation the rights to use, copy, modify, merge, publish, */
14 /* distribute, sublicense, and/or sell copies of the Software, and to */
15 /* permit persons to whom the Software is furnished to do so, subject to */
16 /* the following conditions: */
17 /* */
18 /* The above copyright notice and this permission notice shall be */
19 /* included in all copies or substantial portions of the Software. */
20 /* */
21 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
22 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
23 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
24 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
25 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
26 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
27 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
28 /*************************************************************************/
29 #ifndef COMMAND_QUEUE_MT_H
30 #define COMMAND_QUEUE_MT_H
31 
32 #include "typedefs.h"
33 #include "os/semaphore.h"
34 #include "os/mutex.h"
35 #include "os/memory.h"
36 #include "simple_type.h"
42 
43  struct SyncSemaphore {
44 
45  Semaphore *sem;
46  bool in_use;
47  };
48 
49  struct CommandBase {
50 
51  virtual void call()=0;
52  virtual ~CommandBase() {};
53  };
54 
55  template<class T,class M>
56  struct Command0 : public CommandBase {
57 
58  T*instance;
59  M method;
60 
61  virtual void call() { (instance->*method)(); }
62  };
63 
64  template<class T,class M,class P1>
65  struct Command1 : public CommandBase {
66 
67  T*instance;
68  M method;
69  typename GetSimpleTypeT<P1>::type_t p1;
70 
71  virtual void call() { (instance->*method)(p1); }
72  };
73 
74  template<class T,class M,class P1,class P2>
75  struct Command2 : public CommandBase {
76 
77  T*instance;
78  M method;
79  typename GetSimpleTypeT<P1>::type_t p1;
80  typename GetSimpleTypeT<P2>::type_t p2;
81 
82  virtual void call() { (instance->*method)(p1,p2); }
83  };
84 
85  template<class T,class M,class P1,class P2,class P3>
86  struct Command3 : public CommandBase {
87 
88  T*instance;
89  M method;
90  typename GetSimpleTypeT<P1>::type_t p1;
91  typename GetSimpleTypeT<P2>::type_t p2;
92  typename GetSimpleTypeT<P3>::type_t p3;
93 
94  virtual void call() { (instance->*method)(p1,p2,p3); }
95  };
96 
97  template<class T,class M,class P1,class P2,class P3,class P4>
98  struct Command4 : public CommandBase {
99 
100  T*instance;
101  M method;
102  typename GetSimpleTypeT<P1>::type_t p1;
103  typename GetSimpleTypeT<P2>::type_t p2;
104  typename GetSimpleTypeT<P3>::type_t p3;
105  typename GetSimpleTypeT<P4>::type_t p4;
106 
107  virtual void call() { (instance->*method)(p1,p2,p3,p4); }
108  };
109 
110  template<class T,class M,class P1,class P2,class P3,class P4,class P5>
111  struct Command5 : public CommandBase {
112 
113  T*instance;
114  M method;
115  typename GetSimpleTypeT<P1>::type_t p1;
116  typename GetSimpleTypeT<P2>::type_t p2;
117  typename GetSimpleTypeT<P3>::type_t p3;
118  typename GetSimpleTypeT<P4>::type_t p4;
119  typename GetSimpleTypeT<P5>::type_t p5;
120 
121  virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); }
122  };
123 
124  template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6>
125  struct Command6 : public CommandBase {
126 
127  T*instance;
128  M method;
129  typename GetSimpleTypeT<P1>::type_t p1;
130  typename GetSimpleTypeT<P2>::type_t p2;
131  typename GetSimpleTypeT<P3>::type_t p3;
132  typename GetSimpleTypeT<P4>::type_t p4;
133  typename GetSimpleTypeT<P5>::type_t p5;
134  typename GetSimpleTypeT<P6>::type_t p6;
135 
136  virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); }
137  };
138 
139  template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7>
140  struct Command7 : public CommandBase {
141 
142  T*instance;
143  M method;
144  typename GetSimpleTypeT<P1>::type_t p1;
145  typename GetSimpleTypeT<P2>::type_t p2;
146  typename GetSimpleTypeT<P3>::type_t p3;
147  typename GetSimpleTypeT<P4>::type_t p4;
148  typename GetSimpleTypeT<P5>::type_t p5;
149  typename GetSimpleTypeT<P6>::type_t p6;
150  typename GetSimpleTypeT<P7>::type_t p7;
151 
152  virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); }
153  };
154 
155  /* comands that return */
156 
157  template<class T,class M,class R>
158  struct CommandRet0 : public CommandBase {
159 
160  T*instance;
161  M method;
162  R* ret;
163  SyncSemaphore *sync;
164 
165  virtual void call() { *ret = (instance->*method)(); sync->sem->post(); sync->in_use=false; ; }
166  };
167 
168  template<class T,class M,class P1,class R>
169  struct CommandRet1 : public CommandBase {
170 
171  T*instance;
172  M method;
173  typename GetSimpleTypeT<P1>::type_t p1;
174  R* ret;
175  SyncSemaphore *sync;
176 
177  virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); sync->in_use=false; }
178  };
179 
180  template<class T,class M,class P1,class P2,class R>
181  struct CommandRet2 : public CommandBase {
182 
183  T*instance;
184  M method;
185  typename GetSimpleTypeT<P1>::type_t p1;
186  typename GetSimpleTypeT<P2>::type_t p2;
187  R* ret;
188  SyncSemaphore *sync;
189 
190  virtual void call() { *ret = (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; }
191  };
192 
193  template<class T,class M,class P1,class P2,class P3,class R>
194  struct CommandRet3 : public CommandBase {
195 
196  T*instance;
197  M method;
198  typename GetSimpleTypeT<P1>::type_t p1;
199  typename GetSimpleTypeT<P2>::type_t p2;
200  typename GetSimpleTypeT<P3>::type_t p3;
201  R* ret;
202  SyncSemaphore *sync;
203 
204  virtual void call() { *ret = (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; }
205  };
206 
207  template<class T,class M,class P1,class P2,class P3,class P4,class R>
208  struct CommandRet4 : public CommandBase {
209 
210  T*instance;
211  M method;
212  typename GetSimpleTypeT<P1>::type_t p1;
213  typename GetSimpleTypeT<P2>::type_t p2;
214  typename GetSimpleTypeT<P3>::type_t p3;
215  typename GetSimpleTypeT<P4>::type_t p4;
216  R* ret;
217  SyncSemaphore *sync;
218 
219  virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; }
220  };
221 
222  template<class T,class M,class P1,class P2,class P3,class P4,class P5,class R>
223  struct CommandRet5 : public CommandBase {
224 
225  T*instance;
226  M method;
227  typename GetSimpleTypeT<P1>::type_t p1;
228  typename GetSimpleTypeT<P2>::type_t p2;
229  typename GetSimpleTypeT<P3>::type_t p3;
230  typename GetSimpleTypeT<P4>::type_t p4;
231  typename GetSimpleTypeT<P5>::type_t p5;
232  R* ret;
233  SyncSemaphore *sync;
234 
235  virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5); sync->sem->post(); sync->in_use=false; ; }
236  };
237 
238  template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class R>
239  struct CommandRet6 : public CommandBase {
240 
241  T*instance;
242  M method;
243  typename GetSimpleTypeT<P1>::type_t p1;
244  typename GetSimpleTypeT<P2>::type_t p2;
245  typename GetSimpleTypeT<P3>::type_t p3;
246  typename GetSimpleTypeT<P4>::type_t p4;
247  typename GetSimpleTypeT<P5>::type_t p5;
248  typename GetSimpleTypeT<P6>::type_t p6;
249  R* ret;
250  SyncSemaphore *sync;
251 
252  virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; }
253  };
254 
255  template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class R>
256  struct CommandRet7 : public CommandBase {
257 
258  T*instance;
259  M method;
260  typename GetSimpleTypeT<P1>::type_t p1;
261  typename GetSimpleTypeT<P2>::type_t p2;
262  typename GetSimpleTypeT<P3>::type_t p3;
263  typename GetSimpleTypeT<P4>::type_t p4;
264  typename GetSimpleTypeT<P5>::type_t p5;
265  typename GetSimpleTypeT<P6>::type_t p6;
266  typename GetSimpleTypeT<P7>::type_t p7;
267  R* ret;
268  SyncSemaphore *sync;
269 
270  virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
271  };
272 
275  /* comands that return */
276 
277  template<class T,class M>
278  struct CommandSync0 : public CommandBase {
279 
280  T*instance;
281  M method;
282 
283  SyncSemaphore *sync;
284 
285  virtual void call() { (instance->*method)(); sync->sem->post(); sync->in_use=false; ; }
286  };
287 
288  template<class T,class M,class P1>
289  struct CommandSync1 : public CommandBase {
290 
291  T*instance;
292  M method;
293  typename GetSimpleTypeT<P1>::type_t p1;
294 
295  SyncSemaphore *sync;
296 
297  virtual void call() { (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; }
298  };
299 
300  template<class T,class M,class P1,class P2>
301  struct CommandSync2 : public CommandBase {
302 
303  T*instance;
304  M method;
305  typename GetSimpleTypeT<P1>::type_t p1;
306  typename GetSimpleTypeT<P2>::type_t p2;
307 
308  SyncSemaphore *sync;
309 
310  virtual void call() { (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; }
311  };
312 
313  template<class T,class M,class P1,class P2,class P3>
314  struct CommandSync3 : public CommandBase {
315 
316  T*instance;
317  M method;
318  typename GetSimpleTypeT<P1>::type_t p1;
319  typename GetSimpleTypeT<P2>::type_t p2;
320  typename GetSimpleTypeT<P3>::type_t p3;
321 
322  SyncSemaphore *sync;
323 
324  virtual void call() { (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; }
325  };
326 
327  template<class T,class M,class P1,class P2,class P3,class P4>
328  struct CommandSync4 : public CommandBase {
329 
330  T*instance;
331  M method;
332  typename GetSimpleTypeT<P1>::type_t p1;
333  typename GetSimpleTypeT<P2>::type_t p2;
334  typename GetSimpleTypeT<P3>::type_t p3;
335  typename GetSimpleTypeT<P4>::type_t p4;
336 
337  SyncSemaphore *sync;
338 
339  virtual void call() { (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; }
340  };
341 
342  template<class T,class M,class P1,class P2,class P3,class P4,class P5>
343  struct CommandSync5 : public CommandBase {
344 
345  T*instance;
346  M method;
347  typename GetSimpleTypeT<P1>::type_t p1;
348  typename GetSimpleTypeT<P2>::type_t p2;
349  typename GetSimpleTypeT<P3>::type_t p3;
350  typename GetSimpleTypeT<P4>::type_t p4;
351  typename GetSimpleTypeT<P5>::type_t p5;
352 
353  SyncSemaphore *sync;
354 
355  virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); sync->sem->post(); sync->in_use=false; ; }
356  };
357 
358  template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6>
359  struct CommandSync6 : public CommandBase {
360 
361  T*instance;
362  M method;
363  typename GetSimpleTypeT<P1>::type_t p1;
364  typename GetSimpleTypeT<P2>::type_t p2;
365  typename GetSimpleTypeT<P3>::type_t p3;
366  typename GetSimpleTypeT<P4>::type_t p4;
367  typename GetSimpleTypeT<P5>::type_t p5;
368  typename GetSimpleTypeT<P6>::type_t p6;
369 
370  SyncSemaphore *sync;
371 
372  virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; }
373  };
374 
375  template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7>
376  struct CommandSync7 : public CommandBase {
377 
378  T*instance;
379  M method;
380  typename GetSimpleTypeT<P1>::type_t p1;
381  typename GetSimpleTypeT<P2>::type_t p2;
382  typename GetSimpleTypeT<P3>::type_t p3;
383  typename GetSimpleTypeT<P4>::type_t p4;
384  typename GetSimpleTypeT<P5>::type_t p5;
385  typename GetSimpleTypeT<P6>::type_t p6;
386  typename GetSimpleTypeT<P7>::type_t p7;
387 
388  SyncSemaphore *sync;
389 
390  virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
391  };
392 
393  /***** BASE *******/
394 
395  enum {
396  COMMAND_MEM_SIZE_KB=256,
397  COMMAND_MEM_SIZE=COMMAND_MEM_SIZE_KB*1024,
398  SYNC_SEMAPHORES=8
399  };
400 
401 
402  uint8_t command_mem[COMMAND_MEM_SIZE];
403  uint32_t read_ptr;
404  uint32_t write_ptr;
405  SyncSemaphore sync_sems[SYNC_SEMAPHORES];
406  Mutex *mutex;
407  Semaphore *sync;
408 
409 
410  template<class T>
411  T* allocate() {
412 
413  // alloc size is size+T+safeguard
414  uint32_t alloc_size=sizeof(T)+sizeof(uint32_t);
415 
416  tryagain:
417 
418  if (write_ptr < read_ptr) {
419  // behind read_ptr, check that there is room
420  if ( (read_ptr-write_ptr) <= alloc_size )
421  return NULL;
422  } else if (write_ptr >= read_ptr) {
423  // ahead of read_ptr, check that there is room
424 
425 
426  if ( (COMMAND_MEM_SIZE-write_ptr) < alloc_size+4 ) {
427  // no room at the end, wrap down;
428 
429  if (read_ptr==0) // dont want write_ptr to become read_ptr
430  return NULL;
431 
432  // if this happens, it's a bug
433  ERR_FAIL_COND_V( (COMMAND_MEM_SIZE-write_ptr) < sizeof(uint32_t), NULL );
434  // zero means, wrap to begining
435 
436  uint32_t * p = (uint32_t*)&command_mem[write_ptr];
437  *p=0;
438  write_ptr=0;
439  goto tryagain;
440  }
441  }
442  // allocate the size
443  uint32_t * p = (uint32_t*)&command_mem[write_ptr];
444  *p=sizeof(T);
445  write_ptr+=sizeof(uint32_t);
446  // allocate the command
447  T* cmd = memnew_placement( &command_mem[write_ptr], T );
448  write_ptr+=sizeof(T);
449  return cmd;
450 
451  }
452 
453  template<class T>
454  T* allocate_and_lock() {
455 
456  lock();
457  T* ret;
458 
459  while ( (ret=allocate<T>())==NULL ) {
460 
461  unlock();
462  // sleep a little until fetch happened and some room is made
463  wait_for_flush();
464  lock();
465 
466  }
467 
468  return ret;
469  }
470 
471 
472  bool flush_one() {
473 
474  tryagain:
475 
476  // tried to read an empty queue
477  if (read_ptr == write_ptr )
478  return false;
479 
480  uint32_t size = *(uint32_t*)( &command_mem[read_ptr] );
481 
482  if (size==0) {
483  //end of ringbuffer, wrap
484  read_ptr=0;
485  goto tryagain;
486  }
487 
488  read_ptr+=sizeof(uint32_t);
489 
490  CommandBase *cmd = reinterpret_cast<CommandBase*>( &command_mem[read_ptr] );
491 
492  cmd->call();
493  cmd->~CommandBase();
494 
495  read_ptr+=size;
496 
497  return true;
498  }
499 
500 
501  void lock();
502  void unlock();
503  void wait_for_flush();
504  SyncSemaphore* _alloc_sync_sem();
505 
506 
507 public:
508 
509  /* NORMAL PUSH COMMANDS */
510 
511  template<class T, class M>
512  void push( T * p_instance, M p_method ) {
513 
514  Command0<T,M> * cmd = allocate_and_lock< Command0<T,M> >();
515 
516  cmd->instance=p_instance;
517  cmd->method=p_method;
518 
519  unlock();
520 
521  if (sync) sync->post();
522  }
523 
524  template<class T, class M, class P1>
525  void push( T * p_instance, M p_method, P1 p1 ) {
526 
527  Command1<T,M,P1> * cmd = allocate_and_lock< Command1<T,M,P1> >();
528 
529  cmd->instance=p_instance;
530  cmd->method=p_method;
531  cmd->p1=p1;
532 
533  unlock();
534 
535  if (sync) sync->post();
536  }
537 
538  template<class T, class M, class P1, class P2>
539  void push( T * p_instance, M p_method, P1 p1, P2 p2 ) {
540 
541  Command2<T,M,P1,P2> * cmd = allocate_and_lock< Command2<T,M,P1,P2> >();
542 
543  cmd->instance=p_instance;
544  cmd->method=p_method;
545  cmd->p1=p1;
546  cmd->p2=p2;
547 
548  unlock();
549 
550  if (sync) sync->post();
551  }
552 
553  template<class T, class M, class P1, class P2, class P3>
554  void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) {
555 
556  Command3<T,M,P1,P2,P3> * cmd = allocate_and_lock< Command3<T,M,P1,P2,P3> >();
557 
558  cmd->instance=p_instance;
559  cmd->method=p_method;
560  cmd->p1=p1;
561  cmd->p2=p2;
562  cmd->p3=p3;
563 
564  unlock();
565 
566  if (sync) sync->post();
567  }
568 
569  template<class T, class M, class P1, class P2, class P3, class P4>
570  void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) {
571 
572  Command4<T,M,P1,P2,P3,P4> * cmd = allocate_and_lock< Command4<T,M,P1,P2,P3,P4> >();
573 
574  cmd->instance=p_instance;
575  cmd->method=p_method;
576  cmd->p1=p1;
577  cmd->p2=p2;
578  cmd->p3=p3;
579  cmd->p4=p4;
580 
581  unlock();
582 
583  if (sync) sync->post();
584  }
585 
586  template<class T, class M, class P1, class P2, class P3, class P4, class P5>
587  void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) {
588 
589  Command5<T,M,P1,P2,P3,P4,P5> * cmd = allocate_and_lock< Command5<T,M,P1,P2,P3,P4,P5> >();
590 
591  cmd->instance=p_instance;
592  cmd->method=p_method;
593  cmd->p1=p1;
594  cmd->p2=p2;
595  cmd->p3=p3;
596  cmd->p4=p4;
597  cmd->p5=p5;
598 
599  unlock();
600 
601  if (sync) sync->post();
602  }
603 
604  template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
605  void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) {
606 
607  Command6<T,M,P1,P2,P3,P4,P5,P6> * cmd = allocate_and_lock< Command6<T,M,P1,P2,P3,P4,P5,P6> >();
608 
609  cmd->instance=p_instance;
610  cmd->method=p_method;
611  cmd->p1=p1;
612  cmd->p2=p2;
613  cmd->p3=p3;
614  cmd->p4=p4;
615  cmd->p5=p5;
616  cmd->p6=p6;
617 
618  unlock();
619 
620  if (sync) sync->post();
621  }
622 
623  template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
624  void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7 ) {
625 
626  Command7<T,M,P1,P2,P3,P4,P5,P6,P7> * cmd = allocate_and_lock< Command7<T,M,P1,P2,P3,P4,P5,P6,P7> >();
627 
628  cmd->instance=p_instance;
629  cmd->method=p_method;
630  cmd->p1=p1;
631  cmd->p2=p2;
632  cmd->p3=p3;
633  cmd->p4=p4;
634  cmd->p5=p5;
635  cmd->p6=p6;
636  cmd->p7=p7;
637 
638  unlock();
639 
640  if (sync) sync->post();
641  }
642  /*** PUSH AND RET COMMANDS ***/
643 
644 
645  template<class T, class M,class R>
646  void push_and_ret( T * p_instance, M p_method, R* r_ret) {
647 
648  CommandRet0<T,M,R> * cmd = allocate_and_lock< CommandRet0<T,M,R> >();
649 
650  cmd->instance=p_instance;
651  cmd->method=p_method;
652  cmd->ret=r_ret;
653  SyncSemaphore *ss=_alloc_sync_sem();
654  cmd->sync=ss;
655 
656  unlock();
657 
658  if (sync) sync->post();
659  ss->sem->wait();
660  }
661 
662  template<class T, class M, class P1,class R>
663  void push_and_ret( T * p_instance, M p_method, P1 p1, R* r_ret) {
664 
665  CommandRet1<T,M,P1,R> * cmd = allocate_and_lock< CommandRet1<T,M,P1,R> >();
666 
667  cmd->instance=p_instance;
668  cmd->method=p_method;
669  cmd->p1=p1;
670  cmd->ret=r_ret;
671  SyncSemaphore *ss=_alloc_sync_sem();
672  cmd->sync=ss;
673 
674  unlock();
675 
676  if (sync) sync->post();
677  ss->sem->wait();
678  }
679 
680  template<class T, class M, class P1, class P2,class R>
681  void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, R* r_ret) {
682 
683  CommandRet2<T,M,P1,P2,R> * cmd = allocate_and_lock< CommandRet2<T,M,P1,P2,R> >();
684 
685  cmd->instance=p_instance;
686  cmd->method=p_method;
687  cmd->p1=p1;
688  cmd->p2=p2;
689  cmd->ret=r_ret;
690  SyncSemaphore *ss=_alloc_sync_sem();
691  cmd->sync=ss;
692 
693  unlock();
694 
695  if (sync) sync->post();
696  ss->sem->wait();
697  }
698 
699  template<class T, class M, class P1, class P2, class P3,class R>
700  void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, R* r_ret ) {
701 
702  CommandRet3<T,M,P1,P2,P3,R> * cmd = allocate_and_lock< CommandRet3<T,M,P1,P2,P3,R> >();
703 
704  cmd->instance=p_instance;
705  cmd->method=p_method;
706  cmd->p1=p1;
707  cmd->p2=p2;
708  cmd->p3=p3;
709  cmd->ret=r_ret;
710  SyncSemaphore *ss=_alloc_sync_sem();
711  cmd->sync=ss;
712 
713  unlock();
714 
715  if (sync) sync->post();
716  ss->sem->wait();
717  }
718 
719  template<class T, class M, class P1, class P2, class P3, class P4,class R>
720  void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, R* r_ret ) {
721 
722  CommandRet4<T,M,P1,P2,P3,P4,R> * cmd = allocate_and_lock< CommandRet4<T,M,P1,P2,P3,P4,R> >();
723 
724  cmd->instance=p_instance;
725  cmd->method=p_method;
726  cmd->p1=p1;
727  cmd->p2=p2;
728  cmd->p3=p3;
729  cmd->p4=p4;
730  cmd->ret=r_ret;
731  SyncSemaphore *ss=_alloc_sync_sem();
732  cmd->sync=ss;
733 
734  unlock();
735 
736  if (sync) sync->post();
737  ss->sem->wait();
738  }
739 
740  template<class T, class M, class P1, class P2, class P3, class P4, class P5,class R>
741  void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, R* r_ret ) {
742 
743  CommandRet5<T,M,P1,P2,P3,P4,P5,R> * cmd = allocate_and_lock< CommandRet5<T,M,P1,P2,P3,P4,P5,R> >();
744 
745  cmd->instance=p_instance;
746  cmd->method=p_method;
747  cmd->p1=p1;
748  cmd->p2=p2;
749  cmd->p3=p3;
750  cmd->p4=p4;
751  cmd->p5=p5;
752  cmd->ret=r_ret;
753  SyncSemaphore *ss=_alloc_sync_sem();
754  cmd->sync=ss;
755 
756  unlock();
757 
758  if (sync) sync->post();
759  ss->sem->wait();
760  }
761 
762  template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class R>
763  void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, R* r_ret ) {
764 
765  CommandRet6<T,M,P1,P2,P3,P4,P5,P6,R> * cmd = allocate_and_lock< CommandRet6<T,M,P1,P2,P3,P4,P5,P6,R> >();
766 
767  cmd->instance=p_instance;
768  cmd->method=p_method;
769  cmd->p1=p1;
770  cmd->p2=p2;
771  cmd->p3=p3;
772  cmd->p4=p4;
773  cmd->p5=p5;
774  cmd->p6=p6;
775  cmd->ret=r_ret;
776  SyncSemaphore *ss=_alloc_sync_sem();
777  cmd->sync=ss;
778 
779  unlock();
780 
781  if (sync) sync->post();
782  ss->sem->wait();
783  }
784 
785  template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class R>
786  void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7, R* r_ret ) {
787 
788  CommandRet7<T,M,P1,P2,P3,P4,P5,P6,P7,R> * cmd = allocate_and_lock< CommandRet7<T,M,P1,P2,P3,P4,P5,P6,P7,R> >();
789 
790  cmd->instance=p_instance;
791  cmd->method=p_method;
792  cmd->p1=p1;
793  cmd->p2=p2;
794  cmd->p3=p3;
795  cmd->p4=p4;
796  cmd->p5=p5;
797  cmd->p6=p6;
798  cmd->p7=p7;
799  cmd->ret=r_ret;
800  SyncSemaphore *ss=_alloc_sync_sem();
801  cmd->sync=ss;
802 
803  unlock();
804 
805  if (sync) sync->post();
806  ss->sem->wait();
807  }
808 
809 
810  template<class T, class M>
811  void push_and_sync( T * p_instance, M p_method) {
812 
813  CommandSync0<T,M> * cmd = allocate_and_lock< CommandSync0<T,M> >();
814 
815  cmd->instance=p_instance;
816  cmd->method=p_method;
817 
818  SyncSemaphore *ss=_alloc_sync_sem();
819  cmd->sync=ss;
820 
821  unlock();
822 
823  if (sync) sync->post();
824  ss->sem->wait();
825  }
826 
827  template<class T, class M, class P1>
828  void push_and_sync( T * p_instance, M p_method, P1 p1) {
829 
830  CommandSync1<T,M,P1> * cmd = allocate_and_lock< CommandSync1<T,M,P1> >();
831 
832  cmd->instance=p_instance;
833  cmd->method=p_method;
834  cmd->p1=p1;
835 
836  SyncSemaphore *ss=_alloc_sync_sem();
837  cmd->sync=ss;
838 
839  unlock();
840 
841  if (sync) sync->post();
842  ss->sem->wait();
843  }
844 
845  template<class T, class M, class P1, class P2>
846  void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2) {
847 
848  CommandSync2<T,M,P1,P2> * cmd = allocate_and_lock< CommandSync2<T,M,P1,P2> >();
849 
850  cmd->instance=p_instance;
851  cmd->method=p_method;
852  cmd->p1=p1;
853  cmd->p2=p2;
854 
855  SyncSemaphore *ss=_alloc_sync_sem();
856  cmd->sync=ss;
857 
858  unlock();
859 
860  if (sync) sync->post();
861  ss->sem->wait();
862  }
863 
864  template<class T, class M, class P1, class P2, class P3>
865  void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) {
866 
867  CommandSync3<T,M,P1,P2,P3> * cmd = allocate_and_lock< CommandSync3<T,M,P1,P2,P3> >();
868 
869  cmd->instance=p_instance;
870  cmd->method=p_method;
871  cmd->p1=p1;
872  cmd->p2=p2;
873  cmd->p3=p3;
874 
875  SyncSemaphore *ss=_alloc_sync_sem();
876  cmd->sync=ss;
877 
878  unlock();
879 
880  if (sync) sync->post();
881  ss->sem->wait();
882  }
883 
884  template<class T, class M, class P1, class P2, class P3, class P4>
885  void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) {
886 
887  CommandSync4<T,M,P1,P2,P3,P4> * cmd = allocate_and_lock< CommandSync4<T,M,P1,P2,P3,P4> >();
888 
889  cmd->instance=p_instance;
890  cmd->method=p_method;
891  cmd->p1=p1;
892  cmd->p2=p2;
893  cmd->p3=p3;
894  cmd->p4=p4;
895 
896  SyncSemaphore *ss=_alloc_sync_sem();
897  cmd->sync=ss;
898 
899  unlock();
900 
901  if (sync) sync->post();
902  ss->sem->wait();
903  }
904 
905  template<class T, class M, class P1, class P2, class P3, class P4, class P5>
906  void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) {
907 
908  CommandSync5<T,M,P1,P2,P3,P4,P5> * cmd = allocate_and_lock< CommandSync5<T,M,P1,P2,P3,P4,P5> >();
909 
910  cmd->instance=p_instance;
911  cmd->method=p_method;
912  cmd->p1=p1;
913  cmd->p2=p2;
914  cmd->p3=p3;
915  cmd->p4=p4;
916  cmd->p5=p5;
917 
918  SyncSemaphore *ss=_alloc_sync_sem();
919  cmd->sync=ss;
920 
921  unlock();
922 
923  if (sync) sync->post();
924  ss->sem->wait();
925  }
926 
927  template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
928  void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) {
929 
930  CommandSync6<T,M,P1,P2,P3,P4,P5,P6> * cmd = allocate_and_lock< CommandSync6<T,M,P1,P2,P3,P4,P5,P6> >();
931 
932  cmd->instance=p_instance;
933  cmd->method=p_method;
934  cmd->p1=p1;
935  cmd->p2=p2;
936  cmd->p3=p3;
937  cmd->p4=p4;
938  cmd->p5=p5;
939  cmd->p6=p6;
940 
941  SyncSemaphore *ss=_alloc_sync_sem();
942  cmd->sync=ss;
943 
944  unlock();
945 
946  if (sync) sync->post();
947  ss->sem->wait();
948  }
949 
950  template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7>
951  void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7 ) {
952 
953  CommandSync7<T,M,P1,P2,P3,P4,P5,P6,P7> * cmd = allocate_and_lock< CommandSync7<T,M,P1,P2,P3,P4,P5,P6,P7> >();
954 
955  cmd->instance=p_instance;
956  cmd->method=p_method;
957  cmd->p1=p1;
958  cmd->p2=p2;
959  cmd->p3=p3;
960  cmd->p4=p4;
961  cmd->p5=p5;
962  cmd->p6=p6;
963  cmd->p7=p7;
964 
965  SyncSemaphore *ss=_alloc_sync_sem();
966  cmd->sync=ss;
967 
968  unlock();
969 
970  if (sync) sync->post();
971  ss->sem->wait();
972  }
973 
974  void wait_and_flush_one() {
975  ERR_FAIL_COND(!sync);
976  sync->wait();
977  lock();
978  flush_one();
979  unlock();
980  }
981 
982  void flush_all() {
983 
984  //ERR_FAIL_COND(sync);
985  lock();
986  while (true) {
987  bool exit = !flush_one();
988  if (exit)
989  break;
990  }
991  unlock();
992  }
993 
994  CommandQueueMT(bool p_sync);
995  ~CommandQueueMT();
996 
997 };
998 
999 #endif
Definition: command_queue_mt.h:41
Definition: mutex.h:45
virtual Error post()=0
unlock the semaphore, incrementing the value
virtual Error wait()=0
wait until semaphore has positive value, then decrement and pass
Definition: simple_type.h:41
Definition: semaphore.h:37