From 0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 9 Feb 2014 22:10:30 -0300 Subject: GODOT IS OPEN SOURCE --- core/command_queue_mt.h | 999 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 999 insertions(+) create mode 100644 core/command_queue_mt.h (limited to 'core/command_queue_mt.h') diff --git a/core/command_queue_mt.h b/core/command_queue_mt.h new file mode 100644 index 0000000000..8b74b3b561 --- /dev/null +++ b/core/command_queue_mt.h @@ -0,0 +1,999 @@ +/*************************************************************************/ +/* command_queue_mt.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef COMMAND_QUEUE_MT_H +#define COMMAND_QUEUE_MT_H + +#include "typedefs.h" +#include "os/semaphore.h" +#include "os/mutex.h" +#include "os/memory.h" +#include "simple_type.h" +/** + @author Juan Linietsky +*/ + +class CommandQueueMT { + + struct SyncSemaphore { + + Semaphore *sem; + bool in_use; + }; + + struct CommandBase { + + virtual void call()=0; + virtual ~CommandBase() {}; + }; + + template + struct Command0 : public CommandBase { + + T*instance; + M method; + + virtual void call() { (instance->*method)(); } + }; + + template + struct Command1 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + + virtual void call() { (instance->*method)(p1); } + }; + + template + struct Command2 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + + virtual void call() { (instance->*method)(p1,p2); } + }; + + template + struct Command3 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + + virtual void call() { (instance->*method)(p1,p2,p3); } + }; + + template + struct Command4 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + + virtual void call() { (instance->*method)(p1,p2,p3,p4); } + }; + + template + struct Command5 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + typename GetSimpleTypeT::type_t p5; + + virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); } + }; + + template + struct Command6 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + typename GetSimpleTypeT::type_t p5; + typename GetSimpleTypeT::type_t p6; + + virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); } + }; + + template + struct Command7 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + typename GetSimpleTypeT::type_t p5; + typename GetSimpleTypeT::type_t p6; + typename GetSimpleTypeT::type_t p7; + + virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); } + }; + + /* comands that return */ + + template + struct CommandRet0 : public CommandBase { + + T*instance; + M method; + R* ret; + SyncSemaphore *sync; + + virtual void call() { *ret = (instance->*method)(); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandRet1 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + R* ret; + SyncSemaphore *sync; + + virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandRet2 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + R* ret; + SyncSemaphore *sync; + + virtual void call() { *ret = (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandRet3 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + R* ret; + SyncSemaphore *sync; + + virtual void call() { *ret = (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandRet4 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + R* ret; + SyncSemaphore *sync; + + virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandRet5 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + typename GetSimpleTypeT::type_t p5; + R* ret; + SyncSemaphore *sync; + + virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandRet6 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + typename GetSimpleTypeT::type_t p5; + typename GetSimpleTypeT::type_t p6; + R* ret; + SyncSemaphore *sync; + + virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandRet7 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + typename GetSimpleTypeT::type_t p5; + typename GetSimpleTypeT::type_t p6; + typename GetSimpleTypeT::type_t p7; + R* ret; + SyncSemaphore *sync; + + virtual void call() { *ret = (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; } + }; + + /** commands that don't return but sync */ + + /* comands that return */ + + template + struct CommandSync0 : public CommandBase { + + T*instance; + M method; + + SyncSemaphore *sync; + + virtual void call() { (instance->*method)(); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandSync1 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + + SyncSemaphore *sync; + + virtual void call() { (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandSync2 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + + SyncSemaphore *sync; + + virtual void call() { (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandSync3 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + + SyncSemaphore *sync; + + virtual void call() { (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandSync4 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + + SyncSemaphore *sync; + + virtual void call() { (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandSync5 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + typename GetSimpleTypeT::type_t p5; + + SyncSemaphore *sync; + + virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandSync6 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + typename GetSimpleTypeT::type_t p5; + typename GetSimpleTypeT::type_t p6; + + SyncSemaphore *sync; + + virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; } + }; + + template + struct CommandSync7 : public CommandBase { + + T*instance; + M method; + typename GetSimpleTypeT::type_t p1; + typename GetSimpleTypeT::type_t p2; + typename GetSimpleTypeT::type_t p3; + typename GetSimpleTypeT::type_t p4; + typename GetSimpleTypeT::type_t p5; + typename GetSimpleTypeT::type_t p6; + typename GetSimpleTypeT::type_t p7; + + SyncSemaphore *sync; + + virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); sync->sem->post(); sync->in_use=false; ; } + }; + + /***** BASE *******/ + + enum { + COMMAND_MEM_SIZE_KB=256, + COMMAND_MEM_SIZE=COMMAND_MEM_SIZE_KB*1024, + SYNC_SEMAPHORES=8 + }; + + + uint8_t command_mem[COMMAND_MEM_SIZE]; + uint32_t read_ptr; + uint32_t write_ptr; + SyncSemaphore sync_sems[SYNC_SEMAPHORES]; + Mutex *mutex; + Semaphore *sync; + + + template + T* allocate() { + + // alloc size is size+T+safeguard + uint32_t alloc_size=sizeof(T)+sizeof(uint32_t); + + tryagain: + + if (write_ptr < read_ptr) { + // behind read_ptr, check that there is room + if ( (read_ptr-write_ptr) <= alloc_size ) + return NULL; + } else if (write_ptr >= read_ptr) { + // ahead of read_ptr, check that there is room + + + if ( (COMMAND_MEM_SIZE-write_ptr) < alloc_size+4 ) { + // no room at the end, wrap down; + + if (read_ptr==0) // dont want write_ptr to become read_ptr + return NULL; + + // if this happens, it's a bug + ERR_FAIL_COND_V( (COMMAND_MEM_SIZE-write_ptr) < sizeof(uint32_t), NULL ); + // zero means, wrap to begining + + uint32_t * p = (uint32_t*)&command_mem[write_ptr]; + *p=0; + write_ptr=0; + goto tryagain; + } + } + // allocate the size + uint32_t * p = (uint32_t*)&command_mem[write_ptr]; + *p=sizeof(T); + write_ptr+=sizeof(uint32_t); + // allocate the command + T* cmd = memnew_placement( &command_mem[write_ptr], T ); + write_ptr+=sizeof(T); + return cmd; + + } + + template + T* allocate_and_lock() { + + lock(); + T* ret; + + while ( (ret=allocate())==NULL ) { + + unlock(); + // sleep a little until fetch happened and some room is made + wait_for_flush(); + lock(); + + } + + return ret; + } + + + bool flush_one() { + + tryagain: + + // tried to read an empty queue + if (read_ptr == write_ptr ) + return false; + + uint32_t size = *(uint32_t*)( &command_mem[read_ptr] ); + + if (size==0) { + //end of ringbuffer, wrap + read_ptr=0; + goto tryagain; + } + + read_ptr+=sizeof(uint32_t); + + CommandBase *cmd = reinterpret_cast( &command_mem[read_ptr] ); + + cmd->call(); + cmd->~CommandBase(); + + read_ptr+=size; + + return true; + } + + + void lock(); + void unlock(); + void wait_for_flush(); + SyncSemaphore* _alloc_sync_sem(); + + +public: + + /* NORMAL PUSH COMMANDS */ + + template + void push( T * p_instance, M p_method ) { + + Command0 * cmd = allocate_and_lock< Command0 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + + unlock(); + + if (sync) sync->post(); + } + + template + void push( T * p_instance, M p_method, P1 p1 ) { + + Command1 * cmd = allocate_and_lock< Command1 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + + unlock(); + + if (sync) sync->post(); + } + + template + void push( T * p_instance, M p_method, P1 p1, P2 p2 ) { + + Command2 * cmd = allocate_and_lock< Command2 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + + unlock(); + + if (sync) sync->post(); + } + + template + void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) { + + Command3 * cmd = allocate_and_lock< Command3 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + + unlock(); + + if (sync) sync->post(); + } + + template + void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) { + + Command4 * cmd = allocate_and_lock< Command4 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + + unlock(); + + if (sync) sync->post(); + } + + template + void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) { + + Command5 * cmd = allocate_and_lock< Command5 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + + unlock(); + + if (sync) sync->post(); + } + + template + void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) { + + Command6 * cmd = allocate_and_lock< Command6 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + cmd->p6=p6; + + unlock(); + + if (sync) sync->post(); + } + + template + void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7 ) { + + Command7 * cmd = allocate_and_lock< Command7 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + cmd->p6=p6; + cmd->p7=p7; + + unlock(); + + if (sync) sync->post(); + } + /*** PUSH AND RET COMMANDS ***/ + + + template + void push_and_ret( T * p_instance, M p_method, R* r_ret) { + + CommandRet0 * cmd = allocate_and_lock< CommandRet0 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->ret=r_ret; + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_ret( T * p_instance, M p_method, P1 p1, R* r_ret) { + + CommandRet1 * cmd = allocate_and_lock< CommandRet1 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->ret=r_ret; + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, R* r_ret) { + + CommandRet2 * cmd = allocate_and_lock< CommandRet2 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->ret=r_ret; + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, R* r_ret ) { + + CommandRet3 * cmd = allocate_and_lock< CommandRet3 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->ret=r_ret; + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, R* r_ret ) { + + CommandRet4 * cmd = allocate_and_lock< CommandRet4 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->ret=r_ret; + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, R* r_ret ) { + + CommandRet5 * cmd = allocate_and_lock< CommandRet5 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + cmd->ret=r_ret; + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + 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 ) { + + CommandRet6 * cmd = allocate_and_lock< CommandRet6 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + cmd->p6=p6; + cmd->ret=r_ret; + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + 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 ) { + + CommandRet7 * cmd = allocate_and_lock< CommandRet7 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + cmd->p6=p6; + cmd->p7=p7; + cmd->ret=r_ret; + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + + template + void push_and_sync( T * p_instance, M p_method) { + + CommandSync0 * cmd = allocate_and_lock< CommandSync0 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_sync( T * p_instance, M p_method, P1 p1) { + + CommandSync1 * cmd = allocate_and_lock< CommandSync1 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2) { + + CommandSync2 * cmd = allocate_and_lock< CommandSync2 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) { + + CommandSync3 * cmd = allocate_and_lock< CommandSync3 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) { + + CommandSync4 * cmd = allocate_and_lock< CommandSync4 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) { + + CommandSync5 * cmd = allocate_and_lock< CommandSync5 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) { + + CommandSync6 * cmd = allocate_and_lock< CommandSync6 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + cmd->p6=p6; + + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + template + void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6,P7 p7 ) { + + CommandSync7 * cmd = allocate_and_lock< CommandSync7 >(); + + cmd->instance=p_instance; + cmd->method=p_method; + cmd->p1=p1; + cmd->p2=p2; + cmd->p3=p3; + cmd->p4=p4; + cmd->p5=p5; + cmd->p6=p6; + cmd->p7=p7; + + SyncSemaphore *ss=_alloc_sync_sem(); + cmd->sync=ss; + + unlock(); + + if (sync) sync->post(); + ss->sem->wait(); + } + + void wait_and_flush_one() { + ERR_FAIL_COND(!sync); + sync->wait(); + lock(); + flush_one(); + unlock(); + } + + void flush_all() { + + ERR_FAIL_COND(sync); + lock(); + while (true) { + bool exit = !flush_one(); + if (exit) + break; + } + unlock(); + } + + CommandQueueMT(bool p_sync); + ~CommandQueueMT(); + +}; + +#endif -- cgit v1.2.3