command_queue_mt.h 29 KB

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