command_queue_mt.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  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-2014 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. #include "typedefs.h"
  32. #include "os/semaphore.h"
  33. #include "os/mutex.h"
  34. #include "os/memory.h"
  35. #include "simple_type.h"
  36. /**
  37. @author Juan Linietsky <[email protected]>
  38. */
  39. class CommandQueueMT {
  40. struct SyncSemaphore {
  41. Semaphore *sem;
  42. bool in_use;
  43. };
  44. struct CommandBase {
  45. virtual void call()=0;
  46. virtual ~CommandBase() {};
  47. };
  48. template<class T,class M>
  49. struct Command0 : public CommandBase {
  50. T*instance;
  51. M method;
  52. virtual void call() { (instance->*method)(); }
  53. };
  54. template<class T,class M,class P1>
  55. struct Command1 : public CommandBase {
  56. T*instance;
  57. M method;
  58. typename GetSimpleTypeT<P1>::type_t p1;
  59. virtual void call() { (instance->*method)(p1); }
  60. };
  61. template<class T,class M,class P1,class P2>
  62. struct Command2 : public CommandBase {
  63. T*instance;
  64. M method;
  65. typename GetSimpleTypeT<P1>::type_t p1;
  66. typename GetSimpleTypeT<P2>::type_t p2;
  67. virtual void call() { (instance->*method)(p1,p2); }
  68. };
  69. template<class T,class M,class P1,class P2,class P3>
  70. struct Command3 : public CommandBase {
  71. T*instance;
  72. M method;
  73. typename GetSimpleTypeT<P1>::type_t p1;
  74. typename GetSimpleTypeT<P2>::type_t p2;
  75. typename GetSimpleTypeT<P3>::type_t p3;
  76. virtual void call() { (instance->*method)(p1,p2,p3); }
  77. };
  78. template<class T,class M,class P1,class P2,class P3,class P4>
  79. struct Command4 : public CommandBase {
  80. T*instance;
  81. M method;
  82. typename GetSimpleTypeT<P1>::type_t p1;
  83. typename GetSimpleTypeT<P2>::type_t p2;
  84. typename GetSimpleTypeT<P3>::type_t p3;
  85. typename GetSimpleTypeT<P4>::type_t p4;
  86. virtual void call() { (instance->*method)(p1,p2,p3,p4); }
  87. };
  88. template<class T,class M,class P1,class P2,class P3,class P4,class P5>
  89. struct Command5 : public CommandBase {
  90. T*instance;
  91. M method;
  92. typename GetSimpleTypeT<P1>::type_t p1;
  93. typename GetSimpleTypeT<P2>::type_t p2;
  94. typename GetSimpleTypeT<P3>::type_t p3;
  95. typename GetSimpleTypeT<P4>::type_t p4;
  96. typename GetSimpleTypeT<P5>::type_t p5;
  97. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); }
  98. };
  99. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6>
  100. struct Command6 : public CommandBase {
  101. T*instance;
  102. M method;
  103. typename GetSimpleTypeT<P1>::type_t p1;
  104. typename GetSimpleTypeT<P2>::type_t p2;
  105. typename GetSimpleTypeT<P3>::type_t p3;
  106. typename GetSimpleTypeT<P4>::type_t p4;
  107. typename GetSimpleTypeT<P5>::type_t p5;
  108. typename GetSimpleTypeT<P6>::type_t p6;
  109. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); }
  110. };
  111. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7>
  112. struct Command7 : public CommandBase {
  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. typename GetSimpleTypeT<P6>::type_t p6;
  121. typename GetSimpleTypeT<P7>::type_t p7;
  122. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); }
  123. };
  124. /* comands that return */
  125. template<class T,class M,class R>
  126. struct CommandRet0 : public CommandBase {
  127. T*instance;
  128. M method;
  129. R* ret;
  130. SyncSemaphore *sync;
  131. virtual void call() { *ret = (instance->*method)(); sync->sem->post(); sync->in_use=false; ; }
  132. };
  133. template<class T,class M,class P1,class R>
  134. struct CommandRet1 : public CommandBase {
  135. T*instance;
  136. M method;
  137. typename GetSimpleTypeT<P1>::type_t p1;
  138. R* ret;
  139. SyncSemaphore *sync;
  140. virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; }
  141. };
  142. template<class T,class M,class P1,class P2,class R>
  143. struct CommandRet2 : public CommandBase {
  144. T*instance;
  145. M method;
  146. typename GetSimpleTypeT<P1>::type_t p1;
  147. typename GetSimpleTypeT<P2>::type_t p2;
  148. R* ret;
  149. SyncSemaphore *sync;
  150. virtual void call() { *ret = (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; }
  151. };
  152. template<class T,class M,class P1,class P2,class P3,class R>
  153. struct CommandRet3 : public CommandBase {
  154. T*instance;
  155. M method;
  156. typename GetSimpleTypeT<P1>::type_t p1;
  157. typename GetSimpleTypeT<P2>::type_t p2;
  158. typename GetSimpleTypeT<P3>::type_t p3;
  159. R* ret;
  160. SyncSemaphore *sync;
  161. virtual void call() { *ret = (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; }
  162. };
  163. template<class T,class M,class P1,class P2,class P3,class P4,class R>
  164. struct CommandRet4 : public CommandBase {
  165. T*instance;
  166. M method;
  167. typename GetSimpleTypeT<P1>::type_t p1;
  168. typename GetSimpleTypeT<P2>::type_t p2;
  169. typename GetSimpleTypeT<P3>::type_t p3;
  170. typename GetSimpleTypeT<P4>::type_t p4;
  171. R* ret;
  172. SyncSemaphore *sync;
  173. virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; }
  174. };
  175. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class R>
  176. struct CommandRet5 : public CommandBase {
  177. T*instance;
  178. M method;
  179. typename GetSimpleTypeT<P1>::type_t p1;
  180. typename GetSimpleTypeT<P2>::type_t p2;
  181. typename GetSimpleTypeT<P3>::type_t p3;
  182. typename GetSimpleTypeT<P4>::type_t p4;
  183. typename GetSimpleTypeT<P5>::type_t p5;
  184. R* ret;
  185. SyncSemaphore *sync;
  186. virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5); sync->sem->post(); sync->in_use=false; ; }
  187. };
  188. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class R>
  189. struct CommandRet6 : public CommandBase {
  190. T*instance;
  191. M method;
  192. typename GetSimpleTypeT<P1>::type_t p1;
  193. typename GetSimpleTypeT<P2>::type_t p2;
  194. typename GetSimpleTypeT<P3>::type_t p3;
  195. typename GetSimpleTypeT<P4>::type_t p4;
  196. typename GetSimpleTypeT<P5>::type_t p5;
  197. typename GetSimpleTypeT<P6>::type_t p6;
  198. R* ret;
  199. SyncSemaphore *sync;
  200. virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; }
  201. };
  202. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class R>
  203. struct CommandRet7 : public CommandBase {
  204. T*instance;
  205. M method;
  206. typename GetSimpleTypeT<P1>::type_t p1;
  207. typename GetSimpleTypeT<P2>::type_t p2;
  208. typename GetSimpleTypeT<P3>::type_t p3;
  209. typename GetSimpleTypeT<P4>::type_t p4;
  210. typename GetSimpleTypeT<P5>::type_t p5;
  211. typename GetSimpleTypeT<P6>::type_t p6;
  212. typename GetSimpleTypeT<P7>::type_t p7;
  213. R* ret;
  214. SyncSemaphore *sync;
  215. virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
  216. };
  217. /** commands that don't return but sync */
  218. /* comands that return */
  219. template<class T,class M>
  220. struct CommandSync0 : public CommandBase {
  221. T*instance;
  222. M method;
  223. SyncSemaphore *sync;
  224. virtual void call() { (instance->*method)(); sync->sem->post(); sync->in_use=false; ; }
  225. };
  226. template<class T,class M,class P1>
  227. struct CommandSync1 : public CommandBase {
  228. T*instance;
  229. M method;
  230. typename GetSimpleTypeT<P1>::type_t p1;
  231. SyncSemaphore *sync;
  232. virtual void call() { (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; }
  233. };
  234. template<class T,class M,class P1,class P2>
  235. struct CommandSync2 : public CommandBase {
  236. T*instance;
  237. M method;
  238. typename GetSimpleTypeT<P1>::type_t p1;
  239. typename GetSimpleTypeT<P2>::type_t p2;
  240. SyncSemaphore *sync;
  241. virtual void call() { (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; }
  242. };
  243. template<class T,class M,class P1,class P2,class P3>
  244. struct CommandSync3 : public CommandBase {
  245. T*instance;
  246. M method;
  247. typename GetSimpleTypeT<P1>::type_t p1;
  248. typename GetSimpleTypeT<P2>::type_t p2;
  249. typename GetSimpleTypeT<P3>::type_t p3;
  250. SyncSemaphore *sync;
  251. virtual void call() { (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; }
  252. };
  253. template<class T,class M,class P1,class P2,class P3,class P4>
  254. struct CommandSync4 : public CommandBase {
  255. T*instance;
  256. M method;
  257. typename GetSimpleTypeT<P1>::type_t p1;
  258. typename GetSimpleTypeT<P2>::type_t p2;
  259. typename GetSimpleTypeT<P3>::type_t p3;
  260. typename GetSimpleTypeT<P4>::type_t p4;
  261. SyncSemaphore *sync;
  262. virtual void call() { (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; }
  263. };
  264. template<class T,class M,class P1,class P2,class P3,class P4,class P5>
  265. struct CommandSync5 : public CommandBase {
  266. T*instance;
  267. M method;
  268. typename GetSimpleTypeT<P1>::type_t p1;
  269. typename GetSimpleTypeT<P2>::type_t p2;
  270. typename GetSimpleTypeT<P3>::type_t p3;
  271. typename GetSimpleTypeT<P4>::type_t p4;
  272. typename GetSimpleTypeT<P5>::type_t p5;
  273. SyncSemaphore *sync;
  274. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); sync->sem->post(); sync->in_use=false; ; }
  275. };
  276. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6>
  277. struct CommandSync6 : public CommandBase {
  278. T*instance;
  279. M method;
  280. typename GetSimpleTypeT<P1>::type_t p1;
  281. typename GetSimpleTypeT<P2>::type_t p2;
  282. typename GetSimpleTypeT<P3>::type_t p3;
  283. typename GetSimpleTypeT<P4>::type_t p4;
  284. typename GetSimpleTypeT<P5>::type_t p5;
  285. typename GetSimpleTypeT<P6>::type_t p6;
  286. SyncSemaphore *sync;
  287. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; }
  288. };
  289. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7>
  290. struct CommandSync7 : public CommandBase {
  291. T*instance;
  292. M method;
  293. typename GetSimpleTypeT<P1>::type_t p1;
  294. typename GetSimpleTypeT<P2>::type_t p2;
  295. typename GetSimpleTypeT<P3>::type_t p3;
  296. typename GetSimpleTypeT<P4>::type_t p4;
  297. typename GetSimpleTypeT<P5>::type_t p5;
  298. typename GetSimpleTypeT<P6>::type_t p6;
  299. typename GetSimpleTypeT<P7>::type_t p7;
  300. SyncSemaphore *sync;
  301. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
  302. };
  303. /***** BASE *******/
  304. enum {
  305. COMMAND_MEM_SIZE_KB=256,
  306. COMMAND_MEM_SIZE=COMMAND_MEM_SIZE_KB*1024,
  307. SYNC_SEMAPHORES=8
  308. };
  309. uint8_t command_mem[COMMAND_MEM_SIZE];
  310. uint32_t read_ptr;
  311. uint32_t write_ptr;
  312. SyncSemaphore sync_sems[SYNC_SEMAPHORES];
  313. Mutex *mutex;
  314. Semaphore *sync;
  315. template<class T>
  316. T* allocate() {
  317. // alloc size is size+T+safeguard
  318. uint32_t alloc_size=sizeof(T)+sizeof(uint32_t);
  319. tryagain:
  320. if (write_ptr < read_ptr) {
  321. // behind read_ptr, check that there is room
  322. if ( (read_ptr-write_ptr) <= alloc_size )
  323. return NULL;
  324. } else if (write_ptr >= read_ptr) {
  325. // ahead of read_ptr, check that there is room
  326. if ( (COMMAND_MEM_SIZE-write_ptr) < alloc_size+4 ) {
  327. // no room at the end, wrap down;
  328. if (read_ptr==0) // dont want write_ptr to become read_ptr
  329. return NULL;
  330. // if this happens, it's a bug
  331. ERR_FAIL_COND_V( (COMMAND_MEM_SIZE-write_ptr) < sizeof(uint32_t), NULL );
  332. // zero means, wrap to begining
  333. uint32_t * p = (uint32_t*)&command_mem[write_ptr];
  334. *p=0;
  335. write_ptr=0;
  336. goto tryagain;
  337. }
  338. }
  339. // allocate the size
  340. uint32_t * p = (uint32_t*)&command_mem[write_ptr];
  341. *p=sizeof(T);
  342. write_ptr+=sizeof(uint32_t);
  343. // allocate the command
  344. T* cmd = memnew_placement( &command_mem[write_ptr], T );
  345. write_ptr+=sizeof(T);
  346. return cmd;
  347. }
  348. template<class T>
  349. T* allocate_and_lock() {
  350. lock();
  351. T* ret;
  352. while ( (ret=allocate<T>())==NULL ) {
  353. unlock();
  354. // sleep a little until fetch happened and some room is made
  355. wait_for_flush();
  356. lock();
  357. }
  358. return ret;
  359. }
  360. bool flush_one() {
  361. tryagain:
  362. // tried to read an empty queue
  363. if (read_ptr == write_ptr )
  364. return false;
  365. uint32_t size = *(uint32_t*)( &command_mem[read_ptr] );
  366. if (size==0) {
  367. //end of ringbuffer, wrap
  368. read_ptr=0;
  369. goto tryagain;
  370. }
  371. read_ptr+=sizeof(uint32_t);
  372. CommandBase *cmd = reinterpret_cast<CommandBase*>( &command_mem[read_ptr] );
  373. cmd->call();
  374. cmd->~CommandBase();
  375. read_ptr+=size;
  376. return true;
  377. }
  378. void lock();
  379. void unlock();
  380. void wait_for_flush();
  381. SyncSemaphore* _alloc_sync_sem();
  382. public:
  383. /* NORMAL PUSH COMMANDS */
  384. template<class T, class M>
  385. void push( T * p_instance, M p_method ) {
  386. Command0<T,M> * cmd = allocate_and_lock< Command0<T,M> >();
  387. cmd->instance=p_instance;
  388. cmd->method=p_method;
  389. unlock();
  390. if (sync) sync->post();
  391. }
  392. template<class T, class M, class P1>
  393. void push( T * p_instance, M p_method, P1 p1 ) {
  394. Command1<T,M,P1> * cmd = allocate_and_lock< Command1<T,M,P1> >();
  395. cmd->instance=p_instance;
  396. cmd->method=p_method;
  397. cmd->p1=p1;
  398. unlock();
  399. if (sync) sync->post();
  400. }
  401. template<class T, class M, class P1, class P2>
  402. void push( T * p_instance, M p_method, P1 p1, P2 p2 ) {
  403. Command2<T,M,P1,P2> * cmd = allocate_and_lock< Command2<T,M,P1,P2> >();
  404. cmd->instance=p_instance;
  405. cmd->method=p_method;
  406. cmd->p1=p1;
  407. cmd->p2=p2;
  408. unlock();
  409. if (sync) sync->post();
  410. }
  411. template<class T, class M, class P1, class P2, class P3>
  412. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) {
  413. Command3<T,M,P1,P2,P3> * cmd = allocate_and_lock< Command3<T,M,P1,P2,P3> >();
  414. cmd->instance=p_instance;
  415. cmd->method=p_method;
  416. cmd->p1=p1;
  417. cmd->p2=p2;
  418. cmd->p3=p3;
  419. unlock();
  420. if (sync) sync->post();
  421. }
  422. template<class T, class M, class P1, class P2, class P3, class P4>
  423. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) {
  424. Command4<T,M,P1,P2,P3,P4> * cmd = allocate_and_lock< Command4<T,M,P1,P2,P3,P4> >();
  425. cmd->instance=p_instance;
  426. cmd->method=p_method;
  427. cmd->p1=p1;
  428. cmd->p2=p2;
  429. cmd->p3=p3;
  430. cmd->p4=p4;
  431. unlock();
  432. if (sync) sync->post();
  433. }
  434. template<class T, class M, class P1, class P2, class P3, class P4, class P5>
  435. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) {
  436. Command5<T,M,P1,P2,P3,P4,P5> * cmd = allocate_and_lock< Command5<T,M,P1,P2,P3,P4,P5> >();
  437. cmd->instance=p_instance;
  438. cmd->method=p_method;
  439. cmd->p1=p1;
  440. cmd->p2=p2;
  441. cmd->p3=p3;
  442. cmd->p4=p4;
  443. cmd->p5=p5;
  444. unlock();
  445. if (sync) sync->post();
  446. }
  447. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
  448. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) {
  449. Command6<T,M,P1,P2,P3,P4,P5,P6> * cmd = allocate_and_lock< Command6<T,M,P1,P2,P3,P4,P5,P6> >();
  450. cmd->instance=p_instance;
  451. cmd->method=p_method;
  452. cmd->p1=p1;
  453. cmd->p2=p2;
  454. cmd->p3=p3;
  455. cmd->p4=p4;
  456. cmd->p5=p5;
  457. cmd->p6=p6;
  458. unlock();
  459. if (sync) sync->post();
  460. }
  461. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
  462. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7 ) {
  463. Command7<T,M,P1,P2,P3,P4,P5,P6,P7> * cmd = allocate_and_lock< Command7<T,M,P1,P2,P3,P4,P5,P6,P7> >();
  464. cmd->instance=p_instance;
  465. cmd->method=p_method;
  466. cmd->p1=p1;
  467. cmd->p2=p2;
  468. cmd->p3=p3;
  469. cmd->p4=p4;
  470. cmd->p5=p5;
  471. cmd->p6=p6;
  472. cmd->p7=p7;
  473. unlock();
  474. if (sync) sync->post();
  475. }
  476. /*** PUSH AND RET COMMANDS ***/
  477. template<class T, class M,class R>
  478. void push_and_ret( T * p_instance, M p_method, R* r_ret) {
  479. CommandRet0<T,M,R> * cmd = allocate_and_lock< CommandRet0<T,M,R> >();
  480. cmd->instance=p_instance;
  481. cmd->method=p_method;
  482. cmd->ret=r_ret;
  483. SyncSemaphore *ss=_alloc_sync_sem();
  484. cmd->sync=ss;
  485. unlock();
  486. if (sync) sync->post();
  487. ss->sem->wait();
  488. }
  489. template<class T, class M, class P1,class R>
  490. void push_and_ret( T * p_instance, M p_method, P1 p1, R* r_ret) {
  491. CommandRet1<T,M,P1,R> * cmd = allocate_and_lock< CommandRet1<T,M,P1,R> >();
  492. cmd->instance=p_instance;
  493. cmd->method=p_method;
  494. cmd->p1=p1;
  495. cmd->ret=r_ret;
  496. SyncSemaphore *ss=_alloc_sync_sem();
  497. cmd->sync=ss;
  498. unlock();
  499. if (sync) sync->post();
  500. ss->sem->wait();
  501. }
  502. template<class T, class M, class P1, class P2,class R>
  503. void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, R* r_ret) {
  504. CommandRet2<T,M,P1,P2,R> * cmd = allocate_and_lock< CommandRet2<T,M,P1,P2,R> >();
  505. cmd->instance=p_instance;
  506. cmd->method=p_method;
  507. cmd->p1=p1;
  508. cmd->p2=p2;
  509. cmd->ret=r_ret;
  510. SyncSemaphore *ss=_alloc_sync_sem();
  511. cmd->sync=ss;
  512. unlock();
  513. if (sync) sync->post();
  514. ss->sem->wait();
  515. }
  516. template<class T, class M, class P1, class P2, class P3,class R>
  517. void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, R* r_ret ) {
  518. CommandRet3<T,M,P1,P2,P3,R> * cmd = allocate_and_lock< CommandRet3<T,M,P1,P2,P3,R> >();
  519. cmd->instance=p_instance;
  520. cmd->method=p_method;
  521. cmd->p1=p1;
  522. cmd->p2=p2;
  523. cmd->p3=p3;
  524. cmd->ret=r_ret;
  525. SyncSemaphore *ss=_alloc_sync_sem();
  526. cmd->sync=ss;
  527. unlock();
  528. if (sync) sync->post();
  529. ss->sem->wait();
  530. }
  531. template<class T, class M, class P1, class P2, class P3, class P4,class R>
  532. void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, R* r_ret ) {
  533. CommandRet4<T,M,P1,P2,P3,P4,R> * cmd = allocate_and_lock< CommandRet4<T,M,P1,P2,P3,P4,R> >();
  534. cmd->instance=p_instance;
  535. cmd->method=p_method;
  536. cmd->p1=p1;
  537. cmd->p2=p2;
  538. cmd->p3=p3;
  539. cmd->p4=p4;
  540. cmd->ret=r_ret;
  541. SyncSemaphore *ss=_alloc_sync_sem();
  542. cmd->sync=ss;
  543. unlock();
  544. if (sync) sync->post();
  545. ss->sem->wait();
  546. }
  547. template<class T, class M, class P1, class P2, class P3, class P4, class P5,class R>
  548. void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, R* r_ret ) {
  549. CommandRet5<T,M,P1,P2,P3,P4,P5,R> * cmd = allocate_and_lock< CommandRet5<T,M,P1,P2,P3,P4,P5,R> >();
  550. cmd->instance=p_instance;
  551. cmd->method=p_method;
  552. cmd->p1=p1;
  553. cmd->p2=p2;
  554. cmd->p3=p3;
  555. cmd->p4=p4;
  556. cmd->p5=p5;
  557. cmd->ret=r_ret;
  558. SyncSemaphore *ss=_alloc_sync_sem();
  559. cmd->sync=ss;
  560. unlock();
  561. if (sync) sync->post();
  562. ss->sem->wait();
  563. }
  564. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class R>
  565. 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 ) {
  566. CommandRet6<T,M,P1,P2,P3,P4,P5,P6,R> * cmd = allocate_and_lock< CommandRet6<T,M,P1,P2,P3,P4,P5,P6,R> >();
  567. cmd->instance=p_instance;
  568. cmd->method=p_method;
  569. cmd->p1=p1;
  570. cmd->p2=p2;
  571. cmd->p3=p3;
  572. cmd->p4=p4;
  573. cmd->p5=p5;
  574. cmd->p6=p6;
  575. cmd->ret=r_ret;
  576. SyncSemaphore *ss=_alloc_sync_sem();
  577. cmd->sync=ss;
  578. unlock();
  579. if (sync) sync->post();
  580. ss->sem->wait();
  581. }
  582. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class R>
  583. 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 ) {
  584. 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> >();
  585. cmd->instance=p_instance;
  586. cmd->method=p_method;
  587. cmd->p1=p1;
  588. cmd->p2=p2;
  589. cmd->p3=p3;
  590. cmd->p4=p4;
  591. cmd->p5=p5;
  592. cmd->p6=p6;
  593. cmd->p7=p7;
  594. cmd->ret=r_ret;
  595. SyncSemaphore *ss=_alloc_sync_sem();
  596. cmd->sync=ss;
  597. unlock();
  598. if (sync) sync->post();
  599. ss->sem->wait();
  600. }
  601. template<class T, class M>
  602. void push_and_sync( T * p_instance, M p_method) {
  603. CommandSync0<T,M> * cmd = allocate_and_lock< CommandSync0<T,M> >();
  604. cmd->instance=p_instance;
  605. cmd->method=p_method;
  606. SyncSemaphore *ss=_alloc_sync_sem();
  607. cmd->sync=ss;
  608. unlock();
  609. if (sync) sync->post();
  610. ss->sem->wait();
  611. }
  612. template<class T, class M, class P1>
  613. void push_and_sync( T * p_instance, M p_method, P1 p1) {
  614. CommandSync1<T,M,P1> * cmd = allocate_and_lock< CommandSync1<T,M,P1> >();
  615. cmd->instance=p_instance;
  616. cmd->method=p_method;
  617. cmd->p1=p1;
  618. SyncSemaphore *ss=_alloc_sync_sem();
  619. cmd->sync=ss;
  620. unlock();
  621. if (sync) sync->post();
  622. ss->sem->wait();
  623. }
  624. template<class T, class M, class P1, class P2>
  625. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2) {
  626. CommandSync2<T,M,P1,P2> * cmd = allocate_and_lock< CommandSync2<T,M,P1,P2> >();
  627. cmd->instance=p_instance;
  628. cmd->method=p_method;
  629. cmd->p1=p1;
  630. cmd->p2=p2;
  631. SyncSemaphore *ss=_alloc_sync_sem();
  632. cmd->sync=ss;
  633. unlock();
  634. if (sync) sync->post();
  635. ss->sem->wait();
  636. }
  637. template<class T, class M, class P1, class P2, class P3>
  638. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) {
  639. CommandSync3<T,M,P1,P2,P3> * cmd = allocate_and_lock< CommandSync3<T,M,P1,P2,P3> >();
  640. cmd->instance=p_instance;
  641. cmd->method=p_method;
  642. cmd->p1=p1;
  643. cmd->p2=p2;
  644. cmd->p3=p3;
  645. SyncSemaphore *ss=_alloc_sync_sem();
  646. cmd->sync=ss;
  647. unlock();
  648. if (sync) sync->post();
  649. ss->sem->wait();
  650. }
  651. template<class T, class M, class P1, class P2, class P3, class P4>
  652. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) {
  653. CommandSync4<T,M,P1,P2,P3,P4> * cmd = allocate_and_lock< CommandSync4<T,M,P1,P2,P3,P4> >();
  654. cmd->instance=p_instance;
  655. cmd->method=p_method;
  656. cmd->p1=p1;
  657. cmd->p2=p2;
  658. cmd->p3=p3;
  659. cmd->p4=p4;
  660. SyncSemaphore *ss=_alloc_sync_sem();
  661. cmd->sync=ss;
  662. unlock();
  663. if (sync) sync->post();
  664. ss->sem->wait();
  665. }
  666. template<class T, class M, class P1, class P2, class P3, class P4, class P5>
  667. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) {
  668. CommandSync5<T,M,P1,P2,P3,P4,P5> * cmd = allocate_and_lock< CommandSync5<T,M,P1,P2,P3,P4,P5> >();
  669. cmd->instance=p_instance;
  670. cmd->method=p_method;
  671. cmd->p1=p1;
  672. cmd->p2=p2;
  673. cmd->p3=p3;
  674. cmd->p4=p4;
  675. cmd->p5=p5;
  676. SyncSemaphore *ss=_alloc_sync_sem();
  677. cmd->sync=ss;
  678. unlock();
  679. if (sync) sync->post();
  680. ss->sem->wait();
  681. }
  682. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
  683. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) {
  684. CommandSync6<T,M,P1,P2,P3,P4,P5,P6> * cmd = allocate_and_lock< CommandSync6<T,M,P1,P2,P3,P4,P5,P6> >();
  685. cmd->instance=p_instance;
  686. cmd->method=p_method;
  687. cmd->p1=p1;
  688. cmd->p2=p2;
  689. cmd->p3=p3;
  690. cmd->p4=p4;
  691. cmd->p5=p5;
  692. cmd->p6=p6;
  693. SyncSemaphore *ss=_alloc_sync_sem();
  694. cmd->sync=ss;
  695. unlock();
  696. if (sync) sync->post();
  697. ss->sem->wait();
  698. }
  699. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7>
  700. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7 ) {
  701. CommandSync7<T,M,P1,P2,P3,P4,P5,P6,P7> * cmd = allocate_and_lock< CommandSync7<T,M,P1,P2,P3,P4,P5,P6,P7> >();
  702. cmd->instance=p_instance;
  703. cmd->method=p_method;
  704. cmd->p1=p1;
  705. cmd->p2=p2;
  706. cmd->p3=p3;
  707. cmd->p4=p4;
  708. cmd->p5=p5;
  709. cmd->p6=p6;
  710. cmd->p7=p7;
  711. SyncSemaphore *ss=_alloc_sync_sem();
  712. cmd->sync=ss;
  713. unlock();
  714. if (sync) sync->post();
  715. ss->sem->wait();
  716. }
  717. void wait_and_flush_one() {
  718. ERR_FAIL_COND(!sync);
  719. sync->wait();
  720. lock();
  721. flush_one();
  722. unlock();
  723. }
  724. void flush_all() {
  725. ERR_FAIL_COND(sync);
  726. lock();
  727. while (true) {
  728. bool exit = !flush_one();
  729. if (exit)
  730. break;
  731. }
  732. unlock();
  733. }
  734. CommandQueueMT(bool p_sync);
  735. ~CommandQueueMT();
  736. };
  737. #endif