virtualx-engine/core/command_queue_mt.h

1203 lines
29 KiB
C++
Raw Normal View History

2014-02-10 02:10:30 +01:00
/*************************************************************************/
/* command_queue_mt.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
2014-02-10 02:10:30 +01:00
/* */
/* 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 "os/memory.h"
#include "os/mutex.h"
#include "os/semaphore.h"
2014-02-10 02:10:30 +01:00
#include "simple_type.h"
#include "typedefs.h"
2014-02-10 02:10:30 +01:00
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
class CommandQueueMT {
struct SyncSemaphore {
Semaphore *sem;
bool in_use;
};
struct CommandBase {
2016-03-09 00:00:52 +01:00
virtual void call() = 0;
virtual ~CommandBase(){};
2014-02-10 02:10:30 +01:00
};
2016-03-09 00:00:52 +01:00
template <class T, class M>
2014-02-10 02:10:30 +01:00
struct Command0 : public CommandBase {
T *instance;
2014-02-10 02:10:30 +01:00
M method;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
virtual void call() { (instance->*method)(); }
};
2016-03-09 00:00:52 +01:00
template <class T, class M, class P1>
2014-02-10 02:10:30 +01:00
struct Command1 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
M method;
typename GetSimpleTypeT<P1>::type_t p1;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
virtual void call() { (instance->*method)(p1); }
};
2016-03-09 00:00:52 +01:00
template <class T, class M, class P1, class P2>
2014-02-10 02:10:30 +01:00
struct Command2 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
2016-03-09 00:00:52 +01:00
virtual void call() { (instance->*method)(p1, p2); }
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3>
2014-02-10 02:10:30 +01:00
struct Command3 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
2016-03-09 00:00:52 +01:00
virtual void call() { (instance->*method)(p1, p2, p3); }
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4>
2014-02-10 02:10:30 +01:00
struct Command4 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
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;
2016-03-09 00:00:52 +01:00
virtual void call() { (instance->*method)(p1, p2, p3, p4); }
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4, class P5>
2014-02-10 02:10:30 +01:00
struct Command5 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
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;
2016-03-09 00:00:52 +01:00
virtual void call() { (instance->*method)(p1, p2, p3, p4, p5); }
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
2014-02-10 02:10:30 +01:00
struct Command6 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
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;
2016-03-09 00:00:52 +01:00
virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6); }
2014-02-10 02:10:30 +01:00
};
2016-03-09 00:00:52 +01:00
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
2014-02-10 02:10:30 +01:00
struct Command7 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
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;
2016-03-09 00:00:52 +01:00
virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7); }
2014-02-10 02:10:30 +01:00
};
2016-03-09 00:00:52 +01:00
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
struct Command8 : 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;
typename GetSimpleTypeT<P8>::type_t p8;
virtual void call() { (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8); }
};
2014-02-10 02:10:30 +01:00
/* comands that return */
2016-03-09 00:00:52 +01:00
template <class T, class M, class R>
2014-02-10 02:10:30 +01:00
struct CommandRet0 : public CommandBase {
T *instance;
2014-02-10 02:10:30 +01:00
M method;
R *ret;
2014-02-10 02:10:30 +01:00
SyncSemaphore *sync;
2016-03-09 00:00:52 +01:00
virtual void call() {
*ret = (instance->*method)();
sync->sem->post();
sync->in_use = false;
;
}
2014-02-10 02:10:30 +01:00
};
2016-03-09 00:00:52 +01:00
template <class T, class M, class P1, class R>
2014-02-10 02:10:30 +01:00
struct CommandRet1 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
M method;
typename GetSimpleTypeT<P1>::type_t p1;
R *ret;
2014-02-10 02:10:30 +01:00
SyncSemaphore *sync;
2016-03-09 00:00:52 +01:00
virtual void call() {
*ret = (instance->*method)(p1);
sync->sem->post();
sync->in_use = false;
}
2014-02-10 02:10:30 +01:00
};
2016-03-09 00:00:52 +01:00
template <class T, class M, class P1, class P2, class R>
2014-02-10 02:10:30 +01:00
struct CommandRet2 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
R *ret;
2014-02-10 02:10:30 +01:00
SyncSemaphore *sync;
2016-03-09 00:00:52 +01:00
virtual void call() {
*ret = (instance->*method)(p1, p2);
sync->sem->post();
sync->in_use = false;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class R>
2014-02-10 02:10:30 +01:00
struct CommandRet3 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
M method;
typename GetSimpleTypeT<P1>::type_t p1;
typename GetSimpleTypeT<P2>::type_t p2;
typename GetSimpleTypeT<P3>::type_t p3;
R *ret;
2014-02-10 02:10:30 +01:00
SyncSemaphore *sync;
2016-03-09 00:00:52 +01:00
virtual void call() {
*ret = (instance->*method)(p1, p2, p3);
sync->sem->post();
sync->in_use = false;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4, class R>
2014-02-10 02:10:30 +01:00
struct CommandRet4 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
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;
2014-02-10 02:10:30 +01:00
SyncSemaphore *sync;
2016-03-09 00:00:52 +01:00
virtual void call() {
*ret = (instance->*method)(p1, p2, p3, p4);
sync->sem->post();
sync->in_use = false;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class R>
2014-02-10 02:10:30 +01:00
struct CommandRet5 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
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;
2014-02-10 02:10:30 +01:00
SyncSemaphore *sync;
2016-03-09 00:00:52 +01:00
virtual void call() {
*ret = (instance->*method)(p1, p2, p3, p4, p5);
sync->sem->post();
sync->in_use = false;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class R>
2014-02-10 02:10:30 +01:00
struct CommandRet6 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
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;
2014-02-10 02:10:30 +01:00
SyncSemaphore *sync;
2016-03-09 00:00:52 +01:00
virtual void call() {
*ret = (instance->*method)(p1, p2, p3, p4, p5, p6);
sync->sem->post();
sync->in_use = false;
;
}
2016-03-09 00:00:52 +01:00
};
2014-02-10 02:10:30 +01:00
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class R>
2014-02-10 02:10:30 +01:00
struct CommandRet7 : public CommandBase {
2016-03-09 00:00:52 +01:00
T *instance;
2014-02-10 02:10:30 +01:00
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;
2014-02-10 02:10:30 +01:00
SyncSemaphore *sync;
2016-03-09 00:00:52 +01:00
virtual void call() {
*ret = (instance->*method)(p1, p2, p3, p4, p5, p6, p7);
sync->sem->post();
sync->in_use = false;
;
}
2016-03-09 00:00:52 +01:00
};
2014-02-10 02:10:30 +01:00
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class R>
struct CommandRet8 : 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;
typename GetSimpleTypeT<P8>::type_t p8;
R *ret;
SyncSemaphore *sync;
virtual void call() {
*ret = (instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8);
sync->sem->post();
sync->in_use = false;
;
}
};
2014-02-10 02:10:30 +01:00
/** commands that don't return but sync */
/* comands that return */
template <class T, class M>
2014-02-10 02:10:30 +01:00
struct CommandSync0 : public CommandBase {
T *instance;
2014-02-10 02:10:30 +01:00
M method;
SyncSemaphore *sync;
virtual void call() {
(instance->*method)();
sync->sem->post();
sync->in_use = false;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1>
2014-02-10 02:10:30 +01:00
struct CommandSync1 : public CommandBase {
T *instance;
2014-02-10 02:10:30 +01:00
M method;
typename GetSimpleTypeT<P1>::type_t p1;
SyncSemaphore *sync;
virtual void call() {
(instance->*method)(p1);
sync->sem->post();
sync->in_use = false;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2>
2014-02-10 02:10:30 +01:00
struct CommandSync2 : public CommandBase {
T *instance;
2014-02-10 02:10:30 +01:00
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;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3>
2014-02-10 02:10:30 +01:00
struct CommandSync3 : public CommandBase {
T *instance;
2014-02-10 02:10:30 +01:00
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;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4>
2014-02-10 02:10:30 +01:00
struct CommandSync4 : public CommandBase {
T *instance;
2014-02-10 02:10:30 +01:00
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;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4, class P5>
2014-02-10 02:10:30 +01:00
struct CommandSync5 : public CommandBase {
T *instance;
2014-02-10 02:10:30 +01:00
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;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6>
2014-02-10 02:10:30 +01:00
struct CommandSync6 : public CommandBase {
T *instance;
2014-02-10 02:10:30 +01:00
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;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7>
2014-02-10 02:10:30 +01:00
struct CommandSync7 : public CommandBase {
T *instance;
2014-02-10 02:10:30 +01:00
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;
;
}
2014-02-10 02:10:30 +01:00
};
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
struct CommandSync8 : 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;
typename GetSimpleTypeT<P8>::type_t p8;
SyncSemaphore *sync;
virtual void call() {
(instance->*method)(p1, p2, p3, p4, p5, p6, p7, p8);
sync->sem->post();
sync->in_use = false;
;
}
};
2014-02-10 02:10:30 +01:00
/***** BASE *******/
2016-03-09 00:00:52 +01:00
enum {
COMMAND_MEM_SIZE_KB = 256,
COMMAND_MEM_SIZE = COMMAND_MEM_SIZE_KB * 1024,
SYNC_SEMAPHORES = 8
2014-02-10 02:10:30 +01:00
};
uint8_t command_mem[COMMAND_MEM_SIZE];
uint32_t read_ptr;
uint32_t write_ptr;
SyncSemaphore sync_sems[SYNC_SEMAPHORES];
Mutex *mutex;
Semaphore *sync;
2016-03-09 00:00:52 +01:00
template <class T>
T *allocate() {
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
// alloc size is size+T+safeguard
uint32_t alloc_size = sizeof(T) + sizeof(uint32_t);
2016-03-09 00:00:52 +01:00
tryagain:
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
if (write_ptr < read_ptr) {
// behind read_ptr, check that there is room
if ((read_ptr - write_ptr) <= alloc_size)
2014-02-10 02:10:30 +01:00
return NULL;
} else if (write_ptr >= read_ptr) {
// ahead of read_ptr, check that there is room
2016-03-09 00:00:52 +01:00
if ((COMMAND_MEM_SIZE - write_ptr) < alloc_size + 4) {
2014-02-10 02:10:30 +01:00
// no room at the end, wrap down;
2016-03-09 00:00:52 +01:00
if (read_ptr == 0) // dont want write_ptr to become read_ptr
2014-02-10 02:10:30 +01:00
return NULL;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
// if this happens, it's a bug
ERR_FAIL_COND_V((COMMAND_MEM_SIZE - write_ptr) < sizeof(uint32_t), NULL);
2014-02-10 02:10:30 +01:00
// zero means, wrap to begining
uint32_t *p = (uint32_t *)&command_mem[write_ptr];
*p = 0;
write_ptr = 0;
2014-02-10 02:10:30 +01:00
goto tryagain;
}
}
// allocate the size
uint32_t *p = (uint32_t *)&command_mem[write_ptr];
*p = sizeof(T);
write_ptr += sizeof(uint32_t);
2014-02-10 02:10:30 +01:00
// allocate the command
T *cmd = memnew_placement(&command_mem[write_ptr], T);
write_ptr += sizeof(T);
2014-02-10 02:10:30 +01:00
return cmd;
}
2016-03-09 00:00:52 +01:00
template <class T>
T *allocate_and_lock() {
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
lock();
T *ret;
2016-03-09 00:00:52 +01:00
while ((ret = allocate<T>()) == NULL) {
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
// sleep a little until fetch happened and some room is made
2014-02-10 02:10:30 +01:00
wait_for_flush();
lock();
}
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
return ret;
}
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
bool flush_one() {
2016-03-09 00:00:52 +01:00
tryagain:
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
// tried to read an empty queue
if (read_ptr == write_ptr)
2014-02-10 02:10:30 +01:00
return false;
2016-03-09 00:00:52 +01:00
uint32_t size = *(uint32_t *)(&command_mem[read_ptr]);
2016-03-09 00:00:52 +01:00
if (size == 0) {
2014-02-10 02:10:30 +01:00
//end of ringbuffer, wrap
read_ptr = 0;
2014-02-10 02:10:30 +01:00
goto tryagain;
}
2016-03-09 00:00:52 +01:00
read_ptr += sizeof(uint32_t);
2016-03-09 00:00:52 +01:00
CommandBase *cmd = reinterpret_cast<CommandBase *>(&command_mem[read_ptr]);
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
cmd->call();
cmd->~CommandBase();
2016-03-09 00:00:52 +01:00
read_ptr += size;
2014-02-10 02:10:30 +01:00
return true;
}
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
void lock();
void unlock();
void wait_for_flush();
SyncSemaphore *_alloc_sync_sem();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
public:
/* NORMAL PUSH COMMANDS */
2016-03-09 00:00:52 +01:00
template <class T, class M>
void push(T *p_instance, M p_method) {
2016-03-09 00:00:52 +01:00
Command0<T, M> *cmd = allocate_and_lock<Command0<T, M> >();
2016-03-09 00:00:52 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
if (sync) sync->post();
}
template <class T, class M, class P1>
void push(T *p_instance, M p_method, P1 p1) {
2016-03-09 00:00:52 +01:00
Command1<T, M, P1> *cmd = allocate_and_lock<Command1<T, M, P1> >();
2016-03-09 00:00:52 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
Command2<T, M, P1, P2> *cmd = allocate_and_lock<Command2<T, M, P1, P2> >();
2016-03-09 00:00:52 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
cmd->p2 = p2;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
Command3<T, M, P1, P2, P3> *cmd = allocate_and_lock<Command3<T, M, P1, P2, P3> >();
2016-03-09 00:00:52 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
cmd->p2 = p2;
cmd->p3 = p3;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
Command4<T, M, P1, P2, P3, P4> *cmd = allocate_and_lock<Command4<T, M, P1, P2, P3, P4> >();
2016-03-09 00:00:52 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
cmd->p2 = p2;
cmd->p3 = p3;
cmd->p4 = p4;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
Command5<T, M, P1, P2, P3, P4, P5> *cmd = allocate_and_lock<Command5<T, M, P1, P2, P3, P4, P5> >();
2016-03-09 00:00:52 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
cmd->p2 = p2;
cmd->p3 = p3;
cmd->p4 = p4;
cmd->p5 = p5;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
Command6<T, M, P1, P2, P3, P4, P5, P6> *cmd = allocate_and_lock<Command6<T, M, P1, P2, P3, P4, P5, P6> >();
2016-03-09 00:00:52 +01:00
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;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
Command7<T, M, P1, P2, P3, P4, P5, P6, P7> *cmd = allocate_and_lock<Command7<T, M, P1, P2, P3, P4, P5, P6, P7> >();
2016-03-09 00:00:52 +01:00
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;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
if (sync) sync->post();
}
template <class T, class M, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>
void push(T *p_instance, M p_method, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {
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> >();
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->p8 = p8;
unlock();
if (sync) sync->post();
}
2014-02-10 02:10:30 +01:00
/*** PUSH AND RET COMMANDS ***/
2016-03-09 00:00:52 +01:00
template <class T, class M, class R>
void push_and_ret(T *p_instance, M p_method, R *r_ret) {
2016-03-09 00:00:52 +01:00
CommandRet0<T, M, R> *cmd = allocate_and_lock<CommandRet0<T, M, R> >();
2016-03-09 00:00:52 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->ret = r_ret;
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
CommandRet1<T, M, P1, R> *cmd = allocate_and_lock<CommandRet1<T, M, P1, R> >();
2016-03-09 00:00:52 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
cmd->ret = r_ret;
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
if (sync) sync->post();
ss->sem->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) {
2016-03-09 00:00:52 +01:00
CommandRet2<T, M, P1, P2, R> *cmd = allocate_and_lock<CommandRet2<T, M, P1, P2, R> >();
2016-03-09 00:00:52 +01:00
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;
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
CommandRet3<T, M, P1, P2, P3, R> *cmd = allocate_and_lock<CommandRet3<T, M, P1, P2, P3, R> >();
2016-03-09 00:00:52 +01:00
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;
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
CommandRet4<T, M, P1, P2, P3, P4, R> *cmd = allocate_and_lock<CommandRet4<T, M, P1, P2, P3, P4, R> >();
2016-03-09 00:00:52 +01:00
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;
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
CommandRet5<T, M, P1, P2, P3, P4, P5, R> *cmd = allocate_and_lock<CommandRet5<T, M, P1, P2, P3, P4, P5, R> >();
2016-03-09 00:00:52 +01:00
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;
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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) {
2016-03-09 00:00:52 +01:00
CommandRet6<T, M, P1, P2, P3, P4, P5, P6, R> *cmd = allocate_and_lock<CommandRet6<T, M, P1, P2, P3, P4, P5, P6, R> >();
2016-03-09 00:00:52 +01:00
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;
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
if (sync) sync->post();
ss->sem->wait();
}
2016-03-09 00:00:52 +01:00
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) {
2016-03-09 00:00:52 +01:00
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> >();
2016-03-09 00:00:52 +01:00
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;
2014-02-10 02:10:30 +01:00
unlock();
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
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 P8, 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, P8 p8, R *r_ret) {
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> >();
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->p8 = p8;
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) {
2014-02-10 02:10:30 +01:00
CommandSync0<T, M> *cmd = allocate_and_lock<CommandSync0<T, M> >();
2014-02-10 02:10:30 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
2014-02-10 02:10:30 +01:00
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
2014-02-10 02:10:30 +01:00
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) {
2014-02-10 02:10:30 +01:00
CommandSync1<T, M, P1> *cmd = allocate_and_lock<CommandSync1<T, M, P1> >();
2014-02-10 02:10:30 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
2014-02-10 02:10:30 +01:00
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
2014-02-10 02:10:30 +01:00
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) {
2014-02-10 02:10:30 +01:00
CommandSync2<T, M, P1, P2> *cmd = allocate_and_lock<CommandSync2<T, M, P1, P2> >();
2014-02-10 02:10:30 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
cmd->p2 = p2;
2014-02-10 02:10:30 +01:00
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
2014-02-10 02:10:30 +01:00
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) {
2014-02-10 02:10:30 +01:00
CommandSync3<T, M, P1, P2, P3> *cmd = allocate_and_lock<CommandSync3<T, M, P1, P2, P3> >();
2014-02-10 02:10:30 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
cmd->p2 = p2;
cmd->p3 = p3;
2014-02-10 02:10:30 +01:00
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
2014-02-10 02:10:30 +01:00
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) {
2014-02-10 02:10:30 +01:00
CommandSync4<T, M, P1, P2, P3, P4> *cmd = allocate_and_lock<CommandSync4<T, M, P1, P2, P3, P4> >();
2014-02-10 02:10:30 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
cmd->p2 = p2;
cmd->p3 = p3;
cmd->p4 = p4;
2014-02-10 02:10:30 +01:00
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
2014-02-10 02:10:30 +01:00
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) {
2014-02-10 02:10:30 +01:00
CommandSync5<T, M, P1, P2, P3, P4, P5> *cmd = allocate_and_lock<CommandSync5<T, M, P1, P2, P3, P4, P5> >();
2014-02-10 02:10:30 +01:00
cmd->instance = p_instance;
cmd->method = p_method;
cmd->p1 = p1;
cmd->p2 = p2;
cmd->p3 = p3;
cmd->p4 = p4;
cmd->p5 = p5;
2014-02-10 02:10:30 +01:00
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
2014-02-10 02:10:30 +01:00
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) {
2014-02-10 02:10:30 +01:00
CommandSync6<T, M, P1, P2, P3, P4, P5, P6> *cmd = allocate_and_lock<CommandSync6<T, M, P1, P2, P3, P4, P5, P6> >();
2014-02-10 02:10:30 +01:00
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;
2014-02-10 02:10:30 +01:00
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
2014-02-10 02:10:30 +01:00
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) {
2014-02-10 02:10:30 +01:00
CommandSync7<T, M, P1, P2, P3, P4, P5, P6, P7> *cmd = allocate_and_lock<CommandSync7<T, M, P1, P2, P3, P4, P5, P6, P7> >();
2014-02-10 02:10:30 +01:00
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;
2014-02-10 02:10:30 +01:00
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
2014-02-10 02:10:30 +01:00
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 P8>
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) {
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> >();
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->p8 = p8;
SyncSemaphore *ss = _alloc_sync_sem();
cmd->sync = ss;
unlock();
if (sync) sync->post();
ss->sem->wait();
}
2014-02-10 02:10:30 +01:00
void wait_and_flush_one() {
ERR_FAIL_COND(!sync);
sync->wait();
lock();
2016-03-09 00:00:52 +01:00
flush_one();
2014-02-10 02:10:30 +01:00
unlock();
}
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
void flush_all() {
2016-03-09 00:00:52 +01:00
//ERR_FAIL_COND(sync);
2014-02-10 02:10:30 +01:00
lock();
while (true) {
bool exit = !flush_one();
if (exit)
break;
}
unlock();
}
2016-03-09 00:00:52 +01:00
2014-02-10 02:10:30 +01:00
CommandQueueMT(bool p_sync);
~CommandQueueMT();
};
#endif