command_queue_mt.h 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  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-2017 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. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class P8>
  125. struct Command8 : public CommandBase {
  126. T*instance;
  127. M method;
  128. typename GetSimpleTypeT<P1>::type_t p1;
  129. typename GetSimpleTypeT<P2>::type_t p2;
  130. typename GetSimpleTypeT<P3>::type_t p3;
  131. typename GetSimpleTypeT<P4>::type_t p4;
  132. typename GetSimpleTypeT<P5>::type_t p5;
  133. typename GetSimpleTypeT<P6>::type_t p6;
  134. typename GetSimpleTypeT<P7>::type_t p7;
  135. typename GetSimpleTypeT<P8>::type_t p8;
  136. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7,p8); }
  137. };
  138. /* comands that return */
  139. template<class T,class M,class R>
  140. struct CommandRet0 : public CommandBase {
  141. T*instance;
  142. M method;
  143. R* ret;
  144. SyncSemaphore *sync;
  145. virtual void call() { *ret = (instance->*method)(); sync->sem->post(); sync->in_use=false; ; }
  146. };
  147. template<class T,class M,class P1,class R>
  148. struct CommandRet1 : public CommandBase {
  149. T*instance;
  150. M method;
  151. typename GetSimpleTypeT<P1>::type_t p1;
  152. R* ret;
  153. SyncSemaphore *sync;
  154. virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); sync->in_use=false; }
  155. };
  156. template<class T,class M,class P1,class P2,class R>
  157. struct CommandRet2 : public CommandBase {
  158. T*instance;
  159. M method;
  160. typename GetSimpleTypeT<P1>::type_t p1;
  161. typename GetSimpleTypeT<P2>::type_t p2;
  162. R* ret;
  163. SyncSemaphore *sync;
  164. virtual void call() { *ret = (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; }
  165. };
  166. template<class T,class M,class P1,class P2,class P3,class R>
  167. struct CommandRet3 : public CommandBase {
  168. T*instance;
  169. M method;
  170. typename GetSimpleTypeT<P1>::type_t p1;
  171. typename GetSimpleTypeT<P2>::type_t p2;
  172. typename GetSimpleTypeT<P3>::type_t p3;
  173. R* ret;
  174. SyncSemaphore *sync;
  175. virtual void call() { *ret = (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; }
  176. };
  177. template<class T,class M,class P1,class P2,class P3,class P4,class R>
  178. struct CommandRet4 : public CommandBase {
  179. T*instance;
  180. M method;
  181. typename GetSimpleTypeT<P1>::type_t p1;
  182. typename GetSimpleTypeT<P2>::type_t p2;
  183. typename GetSimpleTypeT<P3>::type_t p3;
  184. typename GetSimpleTypeT<P4>::type_t p4;
  185. R* ret;
  186. SyncSemaphore *sync;
  187. virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; }
  188. };
  189. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class R>
  190. struct CommandRet5 : public CommandBase {
  191. T*instance;
  192. M method;
  193. typename GetSimpleTypeT<P1>::type_t p1;
  194. typename GetSimpleTypeT<P2>::type_t p2;
  195. typename GetSimpleTypeT<P3>::type_t p3;
  196. typename GetSimpleTypeT<P4>::type_t p4;
  197. typename GetSimpleTypeT<P5>::type_t p5;
  198. R* ret;
  199. SyncSemaphore *sync;
  200. virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5); 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 R>
  203. struct CommandRet6 : 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. R* ret;
  213. SyncSemaphore *sync;
  214. virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; }
  215. };
  216. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class R>
  217. struct CommandRet7 : public CommandBase {
  218. T*instance;
  219. M method;
  220. typename GetSimpleTypeT<P1>::type_t p1;
  221. typename GetSimpleTypeT<P2>::type_t p2;
  222. typename GetSimpleTypeT<P3>::type_t p3;
  223. typename GetSimpleTypeT<P4>::type_t p4;
  224. typename GetSimpleTypeT<P5>::type_t p5;
  225. typename GetSimpleTypeT<P6>::type_t p6;
  226. typename GetSimpleTypeT<P7>::type_t p7;
  227. R* ret;
  228. SyncSemaphore *sync;
  229. virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
  230. };
  231. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class P8,class R>
  232. struct CommandRet8 : public CommandBase {
  233. T*instance;
  234. M method;
  235. typename GetSimpleTypeT<P1>::type_t p1;
  236. typename GetSimpleTypeT<P2>::type_t p2;
  237. typename GetSimpleTypeT<P3>::type_t p3;
  238. typename GetSimpleTypeT<P4>::type_t p4;
  239. typename GetSimpleTypeT<P5>::type_t p5;
  240. typename GetSimpleTypeT<P6>::type_t p6;
  241. typename GetSimpleTypeT<P7>::type_t p7;
  242. typename GetSimpleTypeT<P8>::type_t p8;
  243. R* ret;
  244. SyncSemaphore *sync;
  245. virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7,p8); sync->sem->post(); sync->in_use=false; ; }
  246. };
  247. /** commands that don't return but sync */
  248. /* comands that return */
  249. template<class T,class M>
  250. struct CommandSync0 : public CommandBase {
  251. T*instance;
  252. M method;
  253. SyncSemaphore *sync;
  254. virtual void call() { (instance->*method)(); sync->sem->post(); sync->in_use=false; ; }
  255. };
  256. template<class T,class M,class P1>
  257. struct CommandSync1 : public CommandBase {
  258. T*instance;
  259. M method;
  260. typename GetSimpleTypeT<P1>::type_t p1;
  261. SyncSemaphore *sync;
  262. virtual void call() { (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; }
  263. };
  264. template<class T,class M,class P1,class P2>
  265. struct CommandSync2 : public CommandBase {
  266. T*instance;
  267. M method;
  268. typename GetSimpleTypeT<P1>::type_t p1;
  269. typename GetSimpleTypeT<P2>::type_t p2;
  270. SyncSemaphore *sync;
  271. virtual void call() { (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; }
  272. };
  273. template<class T,class M,class P1,class P2,class P3>
  274. struct CommandSync3 : public CommandBase {
  275. T*instance;
  276. M method;
  277. typename GetSimpleTypeT<P1>::type_t p1;
  278. typename GetSimpleTypeT<P2>::type_t p2;
  279. typename GetSimpleTypeT<P3>::type_t p3;
  280. SyncSemaphore *sync;
  281. virtual void call() { (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; }
  282. };
  283. template<class T,class M,class P1,class P2,class P3,class P4>
  284. struct CommandSync4 : public CommandBase {
  285. T*instance;
  286. M method;
  287. typename GetSimpleTypeT<P1>::type_t p1;
  288. typename GetSimpleTypeT<P2>::type_t p2;
  289. typename GetSimpleTypeT<P3>::type_t p3;
  290. typename GetSimpleTypeT<P4>::type_t p4;
  291. SyncSemaphore *sync;
  292. virtual void call() { (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; }
  293. };
  294. template<class T,class M,class P1,class P2,class P3,class P4,class P5>
  295. struct CommandSync5 : public CommandBase {
  296. T*instance;
  297. M method;
  298. typename GetSimpleTypeT<P1>::type_t p1;
  299. typename GetSimpleTypeT<P2>::type_t p2;
  300. typename GetSimpleTypeT<P3>::type_t p3;
  301. typename GetSimpleTypeT<P4>::type_t p4;
  302. typename GetSimpleTypeT<P5>::type_t p5;
  303. SyncSemaphore *sync;
  304. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); sync->sem->post(); sync->in_use=false; ; }
  305. };
  306. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6>
  307. struct CommandSync6 : public CommandBase {
  308. T*instance;
  309. M method;
  310. typename GetSimpleTypeT<P1>::type_t p1;
  311. typename GetSimpleTypeT<P2>::type_t p2;
  312. typename GetSimpleTypeT<P3>::type_t p3;
  313. typename GetSimpleTypeT<P4>::type_t p4;
  314. typename GetSimpleTypeT<P5>::type_t p5;
  315. typename GetSimpleTypeT<P6>::type_t p6;
  316. SyncSemaphore *sync;
  317. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; }
  318. };
  319. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7>
  320. struct CommandSync7 : public CommandBase {
  321. T*instance;
  322. M method;
  323. typename GetSimpleTypeT<P1>::type_t p1;
  324. typename GetSimpleTypeT<P2>::type_t p2;
  325. typename GetSimpleTypeT<P3>::type_t p3;
  326. typename GetSimpleTypeT<P4>::type_t p4;
  327. typename GetSimpleTypeT<P5>::type_t p5;
  328. typename GetSimpleTypeT<P6>::type_t p6;
  329. typename GetSimpleTypeT<P7>::type_t p7;
  330. SyncSemaphore *sync;
  331. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; }
  332. };
  333. template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class P8>
  334. struct CommandSync8 : public CommandBase {
  335. T*instance;
  336. M method;
  337. typename GetSimpleTypeT<P1>::type_t p1;
  338. typename GetSimpleTypeT<P2>::type_t p2;
  339. typename GetSimpleTypeT<P3>::type_t p3;
  340. typename GetSimpleTypeT<P4>::type_t p4;
  341. typename GetSimpleTypeT<P5>::type_t p5;
  342. typename GetSimpleTypeT<P6>::type_t p6;
  343. typename GetSimpleTypeT<P7>::type_t p7;
  344. typename GetSimpleTypeT<P8>::type_t p8;
  345. SyncSemaphore *sync;
  346. virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7,p8); sync->sem->post(); sync->in_use=false; ; }
  347. };
  348. /***** BASE *******/
  349. enum {
  350. COMMAND_MEM_SIZE_KB=256,
  351. COMMAND_MEM_SIZE=COMMAND_MEM_SIZE_KB*1024,
  352. SYNC_SEMAPHORES=8
  353. };
  354. uint8_t command_mem[COMMAND_MEM_SIZE];
  355. uint32_t read_ptr;
  356. uint32_t write_ptr;
  357. SyncSemaphore sync_sems[SYNC_SEMAPHORES];
  358. Mutex *mutex;
  359. Semaphore *sync;
  360. template<class T>
  361. T* allocate() {
  362. // alloc size is size+T+safeguard
  363. uint32_t alloc_size=sizeof(T)+sizeof(uint32_t);
  364. tryagain:
  365. if (write_ptr < read_ptr) {
  366. // behind read_ptr, check that there is room
  367. if ( (read_ptr-write_ptr) <= alloc_size )
  368. return NULL;
  369. } else if (write_ptr >= read_ptr) {
  370. // ahead of read_ptr, check that there is room
  371. if ( (COMMAND_MEM_SIZE-write_ptr) < alloc_size+4 ) {
  372. // no room at the end, wrap down;
  373. if (read_ptr==0) // dont want write_ptr to become read_ptr
  374. return NULL;
  375. // if this happens, it's a bug
  376. ERR_FAIL_COND_V( (COMMAND_MEM_SIZE-write_ptr) < sizeof(uint32_t), NULL );
  377. // zero means, wrap to begining
  378. uint32_t * p = (uint32_t*)&command_mem[write_ptr];
  379. *p=0;
  380. write_ptr=0;
  381. goto tryagain;
  382. }
  383. }
  384. // allocate the size
  385. uint32_t * p = (uint32_t*)&command_mem[write_ptr];
  386. *p=sizeof(T);
  387. write_ptr+=sizeof(uint32_t);
  388. // allocate the command
  389. T* cmd = memnew_placement( &command_mem[write_ptr], T );
  390. write_ptr+=sizeof(T);
  391. return cmd;
  392. }
  393. template<class T>
  394. T* allocate_and_lock() {
  395. lock();
  396. T* ret;
  397. while ( (ret=allocate<T>())==NULL ) {
  398. unlock();
  399. // sleep a little until fetch happened and some room is made
  400. wait_for_flush();
  401. lock();
  402. }
  403. return ret;
  404. }
  405. bool flush_one() {
  406. tryagain:
  407. // tried to read an empty queue
  408. if (read_ptr == write_ptr )
  409. return false;
  410. uint32_t size = *(uint32_t*)( &command_mem[read_ptr] );
  411. if (size==0) {
  412. //end of ringbuffer, wrap
  413. read_ptr=0;
  414. goto tryagain;
  415. }
  416. read_ptr+=sizeof(uint32_t);
  417. CommandBase *cmd = reinterpret_cast<CommandBase*>( &command_mem[read_ptr] );
  418. cmd->call();
  419. cmd->~CommandBase();
  420. read_ptr+=size;
  421. return true;
  422. }
  423. void lock();
  424. void unlock();
  425. void wait_for_flush();
  426. SyncSemaphore* _alloc_sync_sem();
  427. public:
  428. /* NORMAL PUSH COMMANDS */
  429. template<class T, class M>
  430. void push( T * p_instance, M p_method ) {
  431. Command0<T,M> * cmd = allocate_and_lock< Command0<T,M> >();
  432. cmd->instance=p_instance;
  433. cmd->method=p_method;
  434. unlock();
  435. if (sync) sync->post();
  436. }
  437. template<class T, class M, class P1>
  438. void push( T * p_instance, M p_method, P1 p1 ) {
  439. Command1<T,M,P1> * cmd = allocate_and_lock< Command1<T,M,P1> >();
  440. cmd->instance=p_instance;
  441. cmd->method=p_method;
  442. cmd->p1=p1;
  443. unlock();
  444. if (sync) sync->post();
  445. }
  446. template<class T, class M, class P1, class P2>
  447. void push( T * p_instance, M p_method, P1 p1, P2 p2 ) {
  448. Command2<T,M,P1,P2> * cmd = allocate_and_lock< Command2<T,M,P1,P2> >();
  449. cmd->instance=p_instance;
  450. cmd->method=p_method;
  451. cmd->p1=p1;
  452. cmd->p2=p2;
  453. unlock();
  454. if (sync) sync->post();
  455. }
  456. template<class T, class M, class P1, class P2, class P3>
  457. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) {
  458. Command3<T,M,P1,P2,P3> * cmd = allocate_and_lock< Command3<T,M,P1,P2,P3> >();
  459. cmd->instance=p_instance;
  460. cmd->method=p_method;
  461. cmd->p1=p1;
  462. cmd->p2=p2;
  463. cmd->p3=p3;
  464. unlock();
  465. if (sync) sync->post();
  466. }
  467. template<class T, class M, class P1, class P2, class P3, class P4>
  468. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) {
  469. Command4<T,M,P1,P2,P3,P4> * cmd = allocate_and_lock< Command4<T,M,P1,P2,P3,P4> >();
  470. cmd->instance=p_instance;
  471. cmd->method=p_method;
  472. cmd->p1=p1;
  473. cmd->p2=p2;
  474. cmd->p3=p3;
  475. cmd->p4=p4;
  476. unlock();
  477. if (sync) sync->post();
  478. }
  479. template<class T, class M, class P1, class P2, class P3, class P4, class P5>
  480. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) {
  481. Command5<T,M,P1,P2,P3,P4,P5> * cmd = allocate_and_lock< Command5<T,M,P1,P2,P3,P4,P5> >();
  482. cmd->instance=p_instance;
  483. cmd->method=p_method;
  484. cmd->p1=p1;
  485. cmd->p2=p2;
  486. cmd->p3=p3;
  487. cmd->p4=p4;
  488. cmd->p5=p5;
  489. unlock();
  490. if (sync) sync->post();
  491. }
  492. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
  493. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) {
  494. Command6<T,M,P1,P2,P3,P4,P5,P6> * cmd = allocate_and_lock< Command6<T,M,P1,P2,P3,P4,P5,P6> >();
  495. cmd->instance=p_instance;
  496. cmd->method=p_method;
  497. cmd->p1=p1;
  498. cmd->p2=p2;
  499. cmd->p3=p3;
  500. cmd->p4=p4;
  501. cmd->p5=p5;
  502. cmd->p6=p6;
  503. unlock();
  504. if (sync) sync->post();
  505. }
  506. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
  507. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7 ) {
  508. Command7<T,M,P1,P2,P3,P4,P5,P6,P7> * cmd = allocate_and_lock< Command7<T,M,P1,P2,P3,P4,P5,P6,P7> >();
  509. cmd->instance=p_instance;
  510. cmd->method=p_method;
  511. cmd->p1=p1;
  512. cmd->p2=p2;
  513. cmd->p3=p3;
  514. cmd->p4=p4;
  515. cmd->p5=p5;
  516. cmd->p6=p6;
  517. cmd->p7=p7;
  518. unlock();
  519. if (sync) sync->post();
  520. }
  521. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7,class P8>
  522. void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8 ) {
  523. Command8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> * cmd = allocate_and_lock< Command8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> >();
  524. cmd->instance=p_instance;
  525. cmd->method=p_method;
  526. cmd->p1=p1;
  527. cmd->p2=p2;
  528. cmd->p3=p3;
  529. cmd->p4=p4;
  530. cmd->p5=p5;
  531. cmd->p6=p6;
  532. cmd->p7=p7;
  533. cmd->p8=p8;
  534. unlock();
  535. if (sync) sync->post();
  536. }
  537. /*** PUSH AND RET COMMANDS ***/
  538. template<class T, class M,class R>
  539. void push_and_ret( T * p_instance, M p_method, R* r_ret) {
  540. CommandRet0<T,M,R> * cmd = allocate_and_lock< CommandRet0<T,M,R> >();
  541. cmd->instance=p_instance;
  542. cmd->method=p_method;
  543. cmd->ret=r_ret;
  544. SyncSemaphore *ss=_alloc_sync_sem();
  545. cmd->sync=ss;
  546. unlock();
  547. if (sync) sync->post();
  548. ss->sem->wait();
  549. }
  550. template<class T, class M, class P1,class R>
  551. void push_and_ret( T * p_instance, M p_method, P1 p1, R* r_ret) {
  552. CommandRet1<T,M,P1,R> * cmd = allocate_and_lock< CommandRet1<T,M,P1,R> >();
  553. cmd->instance=p_instance;
  554. cmd->method=p_method;
  555. cmd->p1=p1;
  556. cmd->ret=r_ret;
  557. SyncSemaphore *ss=_alloc_sync_sem();
  558. cmd->sync=ss;
  559. unlock();
  560. if (sync) sync->post();
  561. ss->sem->wait();
  562. }
  563. template<class T, class M, class P1, class P2,class R>
  564. void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, R* r_ret) {
  565. CommandRet2<T,M,P1,P2,R> * cmd = allocate_and_lock< CommandRet2<T,M,P1,P2,R> >();
  566. cmd->instance=p_instance;
  567. cmd->method=p_method;
  568. cmd->p1=p1;
  569. cmd->p2=p2;
  570. cmd->ret=r_ret;
  571. SyncSemaphore *ss=_alloc_sync_sem();
  572. cmd->sync=ss;
  573. unlock();
  574. if (sync) sync->post();
  575. ss->sem->wait();
  576. }
  577. template<class T, class M, class P1, class P2, class P3,class R>
  578. void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, R* r_ret ) {
  579. CommandRet3<T,M,P1,P2,P3,R> * cmd = allocate_and_lock< CommandRet3<T,M,P1,P2,P3,R> >();
  580. cmd->instance=p_instance;
  581. cmd->method=p_method;
  582. cmd->p1=p1;
  583. cmd->p2=p2;
  584. cmd->p3=p3;
  585. cmd->ret=r_ret;
  586. SyncSemaphore *ss=_alloc_sync_sem();
  587. cmd->sync=ss;
  588. unlock();
  589. if (sync) sync->post();
  590. ss->sem->wait();
  591. }
  592. template<class T, class M, class P1, class P2, class P3, class P4,class R>
  593. void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, R* r_ret ) {
  594. CommandRet4<T,M,P1,P2,P3,P4,R> * cmd = allocate_and_lock< CommandRet4<T,M,P1,P2,P3,P4,R> >();
  595. cmd->instance=p_instance;
  596. cmd->method=p_method;
  597. cmd->p1=p1;
  598. cmd->p2=p2;
  599. cmd->p3=p3;
  600. cmd->p4=p4;
  601. cmd->ret=r_ret;
  602. SyncSemaphore *ss=_alloc_sync_sem();
  603. cmd->sync=ss;
  604. unlock();
  605. if (sync) sync->post();
  606. ss->sem->wait();
  607. }
  608. template<class T, class M, class P1, class P2, class P3, class P4, class P5,class R>
  609. void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, R* r_ret ) {
  610. CommandRet5<T,M,P1,P2,P3,P4,P5,R> * cmd = allocate_and_lock< CommandRet5<T,M,P1,P2,P3,P4,P5,R> >();
  611. cmd->instance=p_instance;
  612. cmd->method=p_method;
  613. cmd->p1=p1;
  614. cmd->p2=p2;
  615. cmd->p3=p3;
  616. cmd->p4=p4;
  617. cmd->p5=p5;
  618. cmd->ret=r_ret;
  619. SyncSemaphore *ss=_alloc_sync_sem();
  620. cmd->sync=ss;
  621. unlock();
  622. if (sync) sync->post();
  623. ss->sem->wait();
  624. }
  625. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class R>
  626. 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 ) {
  627. CommandRet6<T,M,P1,P2,P3,P4,P5,P6,R> * cmd = allocate_and_lock< CommandRet6<T,M,P1,P2,P3,P4,P5,P6,R> >();
  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->ret=r_ret;
  637. SyncSemaphore *ss=_alloc_sync_sem();
  638. cmd->sync=ss;
  639. unlock();
  640. if (sync) sync->post();
  641. ss->sem->wait();
  642. }
  643. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class R>
  644. 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 ) {
  645. 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> >();
  646. cmd->instance=p_instance;
  647. cmd->method=p_method;
  648. cmd->p1=p1;
  649. cmd->p2=p2;
  650. cmd->p3=p3;
  651. cmd->p4=p4;
  652. cmd->p5=p5;
  653. cmd->p6=p6;
  654. cmd->p7=p7;
  655. cmd->ret=r_ret;
  656. SyncSemaphore *ss=_alloc_sync_sem();
  657. cmd->sync=ss;
  658. unlock();
  659. if (sync) sync->post();
  660. ss->sem->wait();
  661. }
  662. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class P8,class R>
  663. void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7,P8 p8, R* r_ret ) {
  664. CommandRet8<T,M,P1,P2,P3,P4,P5,P6,P7,P8,R> * cmd = allocate_and_lock< CommandRet8<T,M,P1,P2,P3,P4,P5,P6,P7,P8,R> >();
  665. cmd->instance=p_instance;
  666. cmd->method=p_method;
  667. cmd->p1=p1;
  668. cmd->p2=p2;
  669. cmd->p3=p3;
  670. cmd->p4=p4;
  671. cmd->p5=p5;
  672. cmd->p6=p6;
  673. cmd->p7=p7;
  674. cmd->p8=p8;
  675. cmd->ret=r_ret;
  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>
  683. void push_and_sync( T * p_instance, M p_method) {
  684. CommandSync0<T,M> * cmd = allocate_and_lock< CommandSync0<T,M> >();
  685. cmd->instance=p_instance;
  686. cmd->method=p_method;
  687. SyncSemaphore *ss=_alloc_sync_sem();
  688. cmd->sync=ss;
  689. unlock();
  690. if (sync) sync->post();
  691. ss->sem->wait();
  692. }
  693. template<class T, class M, class P1>
  694. void push_and_sync( T * p_instance, M p_method, P1 p1) {
  695. CommandSync1<T,M,P1> * cmd = allocate_and_lock< CommandSync1<T,M,P1> >();
  696. cmd->instance=p_instance;
  697. cmd->method=p_method;
  698. cmd->p1=p1;
  699. SyncSemaphore *ss=_alloc_sync_sem();
  700. cmd->sync=ss;
  701. unlock();
  702. if (sync) sync->post();
  703. ss->sem->wait();
  704. }
  705. template<class T, class M, class P1, class P2>
  706. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2) {
  707. CommandSync2<T,M,P1,P2> * cmd = allocate_and_lock< CommandSync2<T,M,P1,P2> >();
  708. cmd->instance=p_instance;
  709. cmd->method=p_method;
  710. cmd->p1=p1;
  711. cmd->p2=p2;
  712. SyncSemaphore *ss=_alloc_sync_sem();
  713. cmd->sync=ss;
  714. unlock();
  715. if (sync) sync->post();
  716. ss->sem->wait();
  717. }
  718. template<class T, class M, class P1, class P2, class P3>
  719. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) {
  720. CommandSync3<T,M,P1,P2,P3> * cmd = allocate_and_lock< CommandSync3<T,M,P1,P2,P3> >();
  721. cmd->instance=p_instance;
  722. cmd->method=p_method;
  723. cmd->p1=p1;
  724. cmd->p2=p2;
  725. cmd->p3=p3;
  726. SyncSemaphore *ss=_alloc_sync_sem();
  727. cmd->sync=ss;
  728. unlock();
  729. if (sync) sync->post();
  730. ss->sem->wait();
  731. }
  732. template<class T, class M, class P1, class P2, class P3, class P4>
  733. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) {
  734. CommandSync4<T,M,P1,P2,P3,P4> * cmd = allocate_and_lock< CommandSync4<T,M,P1,P2,P3,P4> >();
  735. cmd->instance=p_instance;
  736. cmd->method=p_method;
  737. cmd->p1=p1;
  738. cmd->p2=p2;
  739. cmd->p3=p3;
  740. cmd->p4=p4;
  741. SyncSemaphore *ss=_alloc_sync_sem();
  742. cmd->sync=ss;
  743. unlock();
  744. if (sync) sync->post();
  745. ss->sem->wait();
  746. }
  747. template<class T, class M, class P1, class P2, class P3, class P4, class P5>
  748. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) {
  749. CommandSync5<T,M,P1,P2,P3,P4,P5> * cmd = allocate_and_lock< CommandSync5<T,M,P1,P2,P3,P4,P5> >();
  750. cmd->instance=p_instance;
  751. cmd->method=p_method;
  752. cmd->p1=p1;
  753. cmd->p2=p2;
  754. cmd->p3=p3;
  755. cmd->p4=p4;
  756. cmd->p5=p5;
  757. SyncSemaphore *ss=_alloc_sync_sem();
  758. cmd->sync=ss;
  759. unlock();
  760. if (sync) sync->post();
  761. ss->sem->wait();
  762. }
  763. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
  764. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) {
  765. CommandSync6<T,M,P1,P2,P3,P4,P5,P6> * cmd = allocate_and_lock< CommandSync6<T,M,P1,P2,P3,P4,P5,P6> >();
  766. cmd->instance=p_instance;
  767. cmd->method=p_method;
  768. cmd->p1=p1;
  769. cmd->p2=p2;
  770. cmd->p3=p3;
  771. cmd->p4=p4;
  772. cmd->p5=p5;
  773. cmd->p6=p6;
  774. SyncSemaphore *ss=_alloc_sync_sem();
  775. cmd->sync=ss;
  776. unlock();
  777. if (sync) sync->post();
  778. ss->sem->wait();
  779. }
  780. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7>
  781. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7 ) {
  782. CommandSync7<T,M,P1,P2,P3,P4,P5,P6,P7> * cmd = allocate_and_lock< CommandSync7<T,M,P1,P2,P3,P4,P5,P6,P7> >();
  783. cmd->instance=p_instance;
  784. cmd->method=p_method;
  785. cmd->p1=p1;
  786. cmd->p2=p2;
  787. cmd->p3=p3;
  788. cmd->p4=p4;
  789. cmd->p5=p5;
  790. cmd->p6=p6;
  791. cmd->p7=p7;
  792. SyncSemaphore *ss=_alloc_sync_sem();
  793. cmd->sync=ss;
  794. unlock();
  795. if (sync) sync->post();
  796. ss->sem->wait();
  797. }
  798. template<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class P8>
  799. void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7,P8 p8) {
  800. CommandSync8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> * cmd = allocate_and_lock< CommandSync8<T,M,P1,P2,P3,P4,P5,P6,P7,P8> >();
  801. cmd->instance=p_instance;
  802. cmd->method=p_method;
  803. cmd->p1=p1;
  804. cmd->p2=p2;
  805. cmd->p3=p3;
  806. cmd->p4=p4;
  807. cmd->p5=p5;
  808. cmd->p6=p6;
  809. cmd->p7=p7;
  810. cmd->p8=p8;
  811. SyncSemaphore *ss=_alloc_sync_sem();
  812. cmd->sync=ss;
  813. unlock();
  814. if (sync) sync->post();
  815. ss->sem->wait();
  816. }
  817. void wait_and_flush_one() {
  818. ERR_FAIL_COND(!sync);
  819. sync->wait();
  820. lock();
  821. flush_one();
  822. unlock();
  823. }
  824. void flush_all() {
  825. //ERR_FAIL_COND(sync);
  826. lock();
  827. while (true) {
  828. bool exit = !flush_one();
  829. if (exit)
  830. break;
  831. }
  832. unlock();
  833. }
  834. CommandQueueMT(bool p_sync);
  835. ~CommandQueueMT();
  836. };
  837. #endif