command_queue_mt.h 29 KB

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