0e71d49ef4
-Fix memory corruption due to using wrong singleton in multithreaded physics, fixes #2760
1002 lines
25 KiB
C++
1002 lines
25 KiB
C++
/*************************************************************************/
|
|
/* command_queue_mt.h */
|
|
/*************************************************************************/
|
|
/* This file is part of: */
|
|
/* GODOT ENGINE */
|
|
/* http://www.godotengine.org */
|
|
/*************************************************************************/
|
|
/* Copyright (c) 2007-2016 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"
|
|
#include "print_string.h"
|
|
/**
|
|
@author Juan Linietsky <reduzio@gmail.com>
|
|
*/
|
|
|
|
class CommandQueueMT {
|
|
|
|
struct SyncSemaphore {
|
|
|
|
Semaphore *sem;
|
|
bool in_use;
|
|
};
|
|
|
|
struct CommandBase {
|
|
|
|
virtual void call()=0;
|
|
virtual ~CommandBase() {};
|
|
};
|
|
|
|
template<class T,class M>
|
|
struct Command0 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
|
|
virtual void call() { (instance->*method)(); }
|
|
};
|
|
|
|
template<class T,class M,class P1>
|
|
struct Command1 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
|
|
virtual void call() { (instance->*method)(p1); }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2>
|
|
struct Command2 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2); }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3>
|
|
struct Command3 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2,p3); }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3,class P4>
|
|
struct Command4 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2,p3,p4); }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3,class P4,class P5>
|
|
struct Command5 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
typename GetSimpleTypeT<P5>::type_t p5;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6>
|
|
struct Command6 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
typename GetSimpleTypeT<P5>::type_t p5;
|
|
typename GetSimpleTypeT<P6>::type_t p6;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7>
|
|
struct Command7 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
typename GetSimpleTypeT<P5>::type_t p5;
|
|
typename GetSimpleTypeT<P6>::type_t p6;
|
|
typename GetSimpleTypeT<P7>::type_t p7;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6,p7); }
|
|
};
|
|
|
|
/* comands that return */
|
|
|
|
template<class T,class M,class R>
|
|
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<class T,class M,class P1,class R>
|
|
struct CommandRet1 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
R* ret;
|
|
SyncSemaphore *sync;
|
|
|
|
virtual void call() { *ret = (instance->*method)(p1); sync->sem->post(); print_line("post"); sync->in_use=false; ; }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class R>
|
|
struct CommandRet2 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
R* ret;
|
|
SyncSemaphore *sync;
|
|
|
|
virtual void call() { *ret = (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3,class R>
|
|
struct CommandRet3 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
R* ret;
|
|
SyncSemaphore *sync;
|
|
|
|
virtual void call() { *ret = (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3,class P4,class R>
|
|
struct CommandRet4 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::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<class T,class M,class P1,class P2,class P3,class P4,class P5,class R>
|
|
struct CommandRet5 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
typename GetSimpleTypeT<P5>::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<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class R>
|
|
struct CommandRet6 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
typename GetSimpleTypeT<P5>::type_t p5;
|
|
typename GetSimpleTypeT<P6>::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<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7,class R>
|
|
struct CommandRet7 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
typename GetSimpleTypeT<P5>::type_t p5;
|
|
typename GetSimpleTypeT<P6>::type_t p6;
|
|
typename GetSimpleTypeT<P7>::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<class T,class M>
|
|
struct CommandSync0 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
|
|
SyncSemaphore *sync;
|
|
|
|
virtual void call() { (instance->*method)(); sync->sem->post(); sync->in_use=false; ; }
|
|
};
|
|
|
|
template<class T,class M,class P1>
|
|
struct CommandSync1 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
|
|
SyncSemaphore *sync;
|
|
|
|
virtual void call() { (instance->*method)(p1); sync->sem->post(); sync->in_use=false; ; }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2>
|
|
struct CommandSync2 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
|
|
SyncSemaphore *sync;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2); sync->sem->post(); sync->in_use=false; ; }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3>
|
|
struct CommandSync3 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
|
|
SyncSemaphore *sync;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2,p3); sync->sem->post(); sync->in_use=false; ; }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3,class P4>
|
|
struct CommandSync4 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
|
|
SyncSemaphore *sync;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2,p3,p4); sync->sem->post(); sync->in_use=false; ; }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3,class P4,class P5>
|
|
struct CommandSync5 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
typename GetSimpleTypeT<P5>::type_t p5;
|
|
|
|
SyncSemaphore *sync;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5); sync->sem->post(); sync->in_use=false; ; }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6>
|
|
struct CommandSync6 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
typename GetSimpleTypeT<P5>::type_t p5;
|
|
typename GetSimpleTypeT<P6>::type_t p6;
|
|
|
|
SyncSemaphore *sync;
|
|
|
|
virtual void call() { (instance->*method)(p1,p2,p3,p4,p5,p6); sync->sem->post(); sync->in_use=false; ; }
|
|
};
|
|
|
|
template<class T,class M,class P1,class P2,class P3,class P4,class P5,class P6,class P7>
|
|
struct CommandSync7 : public CommandBase {
|
|
|
|
T*instance;
|
|
M method;
|
|
typename GetSimpleTypeT<P1>::type_t p1;
|
|
typename GetSimpleTypeT<P2>::type_t p2;
|
|
typename GetSimpleTypeT<P3>::type_t p3;
|
|
typename GetSimpleTypeT<P4>::type_t p4;
|
|
typename GetSimpleTypeT<P5>::type_t p5;
|
|
typename GetSimpleTypeT<P6>::type_t p6;
|
|
typename GetSimpleTypeT<P7>::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<class T>
|
|
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<class T>
|
|
T* allocate_and_lock() {
|
|
|
|
lock();
|
|
T* ret;
|
|
|
|
while ( (ret=allocate<T>())==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<CommandBase*>( &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<class T, class M>
|
|
void push( T * p_instance, M p_method ) {
|
|
|
|
Command0<T,M> * cmd = allocate_and_lock< Command0<T,M> >();
|
|
|
|
cmd->instance=p_instance;
|
|
cmd->method=p_method;
|
|
|
|
unlock();
|
|
|
|
if (sync) sync->post();
|
|
}
|
|
|
|
template<class T, class M, class P1>
|
|
void push( T * p_instance, M p_method, P1 p1 ) {
|
|
|
|
Command1<T,M,P1> * cmd = allocate_and_lock< Command1<T,M,P1> >();
|
|
|
|
cmd->instance=p_instance;
|
|
cmd->method=p_method;
|
|
cmd->p1=p1;
|
|
|
|
unlock();
|
|
|
|
if (sync) sync->post();
|
|
}
|
|
|
|
template<class T, class M, class P1, class P2>
|
|
void push( T * p_instance, M p_method, P1 p1, P2 p2 ) {
|
|
|
|
Command2<T,M,P1,P2> * cmd = allocate_and_lock< Command2<T,M,P1,P2> >();
|
|
|
|
cmd->instance=p_instance;
|
|
cmd->method=p_method;
|
|
cmd->p1=p1;
|
|
cmd->p2=p2;
|
|
|
|
unlock();
|
|
|
|
if (sync) sync->post();
|
|
}
|
|
|
|
template<class T, class M, class P1, class P2, class P3>
|
|
void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) {
|
|
|
|
Command3<T,M,P1,P2,P3> * cmd = allocate_and_lock< Command3<T,M,P1,P2,P3> >();
|
|
|
|
cmd->instance=p_instance;
|
|
cmd->method=p_method;
|
|
cmd->p1=p1;
|
|
cmd->p2=p2;
|
|
cmd->p3=p3;
|
|
|
|
unlock();
|
|
|
|
if (sync) sync->post();
|
|
}
|
|
|
|
template<class T, class M, class P1, class P2, class P3, class P4>
|
|
void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) {
|
|
|
|
Command4<T,M,P1,P2,P3,P4> * cmd = allocate_and_lock< Command4<T,M,P1,P2,P3,P4> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4, class P5>
|
|
void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) {
|
|
|
|
Command5<T,M,P1,P2,P3,P4,P5> * cmd = allocate_and_lock< Command5<T,M,P1,P2,P3,P4,P5> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
|
|
void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) {
|
|
|
|
Command6<T,M,P1,P2,P3,P4,P5,P6> * cmd = allocate_and_lock< Command6<T,M,P1,P2,P3,P4,P5,P6> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
|
|
void push( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7 ) {
|
|
|
|
Command7<T,M,P1,P2,P3,P4,P5,P6,P7> * cmd = allocate_and_lock< Command7<T,M,P1,P2,P3,P4,P5,P6,P7> >();
|
|
|
|
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<class T, class M,class R>
|
|
void push_and_ret( T * p_instance, M p_method, R* r_ret) {
|
|
|
|
CommandRet0<T,M,R> * cmd = allocate_and_lock< CommandRet0<T,M,R> >();
|
|
|
|
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<class T, class M, class P1,class R>
|
|
void push_and_ret( T * p_instance, M p_method, P1 p1, R* r_ret) {
|
|
|
|
CommandRet1<T,M,P1,R> * cmd = allocate_and_lock< CommandRet1<T,M,P1,R> >();
|
|
|
|
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();
|
|
print_line("wait");
|
|
}
|
|
|
|
template<class T, class M, class P1, class P2,class R>
|
|
void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, R* r_ret) {
|
|
|
|
CommandRet2<T,M,P1,P2,R> * cmd = allocate_and_lock< CommandRet2<T,M,P1,P2,R> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3,class R>
|
|
void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, R* r_ret ) {
|
|
|
|
CommandRet3<T,M,P1,P2,P3,R> * cmd = allocate_and_lock< CommandRet3<T,M,P1,P2,P3,R> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4,class R>
|
|
void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, R* r_ret ) {
|
|
|
|
CommandRet4<T,M,P1,P2,P3,P4,R> * cmd = allocate_and_lock< CommandRet4<T,M,P1,P2,P3,P4,R> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4, class P5,class R>
|
|
void push_and_ret( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, R* r_ret ) {
|
|
|
|
CommandRet5<T,M,P1,P2,P3,P4,P5,R> * cmd = allocate_and_lock< CommandRet5<T,M,P1,P2,P3,P4,P5,R> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class R>
|
|
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<T,M,P1,P2,P3,P4,P5,P6,R> * cmd = allocate_and_lock< CommandRet6<T,M,P1,P2,P3,P4,P5,P6,R> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7,class R>
|
|
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<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> >();
|
|
|
|
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<class T, class M>
|
|
void push_and_sync( T * p_instance, M p_method) {
|
|
|
|
CommandSync0<T,M> * cmd = allocate_and_lock< CommandSync0<T,M> >();
|
|
|
|
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<class T, class M, class P1>
|
|
void push_and_sync( T * p_instance, M p_method, P1 p1) {
|
|
|
|
CommandSync1<T,M,P1> * cmd = allocate_and_lock< CommandSync1<T,M,P1> >();
|
|
|
|
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<class T, class M, class P1, class P2>
|
|
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2) {
|
|
|
|
CommandSync2<T,M,P1,P2> * cmd = allocate_and_lock< CommandSync2<T,M,P1,P2> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3>
|
|
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3 ) {
|
|
|
|
CommandSync3<T,M,P1,P2,P3> * cmd = allocate_and_lock< CommandSync3<T,M,P1,P2,P3> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4>
|
|
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4 ) {
|
|
|
|
CommandSync4<T,M,P1,P2,P3,P4> * cmd = allocate_and_lock< CommandSync4<T,M,P1,P2,P3,P4> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4, class P5>
|
|
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) {
|
|
|
|
CommandSync5<T,M,P1,P2,P3,P4,P5> * cmd = allocate_and_lock< CommandSync5<T,M,P1,P2,P3,P4,P5> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
|
|
void push_and_sync( T * p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6 ) {
|
|
|
|
CommandSync6<T,M,P1,P2,P3,P4,P5,P6> * cmd = allocate_and_lock< CommandSync6<T,M,P1,P2,P3,P4,P5,P6> >();
|
|
|
|
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<class T, class M, class P1, class P2, class P3, class P4, class P5, class P6,class P7>
|
|
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<T,M,P1,P2,P3,P4,P5,P6,P7> * cmd = allocate_and_lock< CommandSync7<T,M,P1,P2,P3,P4,P5,P6,P7> >();
|
|
|
|
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
|