tree changes

This commit is contained in:
2020-08-19 00:47:05 +03:00
parent c582d8ff46
commit ccd6a9888f
240 changed files with 30 additions and 12 deletions

925
libs/main/core/piobject.h Normal file
View File

@@ -0,0 +1,925 @@
/*! \file piobject.h
* \brief Base object
*
* This file declare PIObject class and associated macros
*/
/*
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PIOBJECT_H
#define PIOBJECT_H
#include "piinit.h"
#include "pivariant.h"
#include "pimutex.h"
#include "piset.h"
#include "piqueue.h"
#ifdef DOXYGEN
/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER and correct piCoutObj output
#define PIOBJECT(name)
/// \relatesalso PIObject \brief you should use this macro after class declaration to use EVENT and EVENT_HANDLER of parent class, and \a scopeList()
#define PIOBJECT_SUBCLASS(name, parent)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name()
#define EVENT_HANDLER0(ret, name) ret name()
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0)
#define EVENT_HANDLER1(ret, name, type0, var0) ret name(type0 var0)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1)
#define EVENT_HANDLER2(ret, name, type0, var0, type1, var1) ret name(type0 var0, type1 var1)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2)
#define EVENT_HANDLER3(ret, name, type0, var0, type1, var1, type2, var2) ret name(type0 var0, type1 var1, type2 var2)
/// \relatesalso PIObject \brief declare event handler \"event\" with name \"name\" and return type \"ret\", ret name(type0 var0, type1 var1, type2 var2, type3 var3)
#define EVENT_HANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) ret name(type0 var0, type1 var1, type2 var2, type3 var3)
/// \relatesalso PIObject \brief EVENT_HANDLER is synonym of EVENT_HANDLER0
#define EVENT_HANDLER EVENT_HANDLER0
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name()
#define EVENT_VHANDLER0(ret, name) virtual ret name()
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0)
#define EVENT_VHANDLER1(ret, name, type0, var0) virtual ret name(type0 var0)
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1)
#define EVENT_VHANDLER2(ret, name, type0, var0, type1, var1) virtual ret name(type0 var0, type1 var1)
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2)
#define EVENT_VHANDLER3(ret, name, type0, var0, type1, var1, type2, var2) virtual ret name(type0 var0, type1 var1, type2 var2)
/// \relatesalso PIObject \brief declare virtual event handler \"event\" with name \"name\" and return type \"ret\", virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
#define EVENT_VHANDLER4(ret, name, type0, var0, type1, var1, type2, var2, type3, var3) virtual ret name(type0 var0, type1 var1, type2 var2, type3 var3)
/// \relatesalso PIObject \brief EVENT_VHANDLER is synonym of EVENT_VHANDLER0
#define EVENT_VHANDLER EVENT_VHANDLER0
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name();
#define EVENT0(name) void name();
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0);
#define EVENT1(name, type0, var0) void name(type0 var0);
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1);
#define EVENT2(name, type0, var0, type1, var1) void name(type0 var0, type1 var1);
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2);
#define EVENT3(name, type0, var0, type1, var1, type2, var2) void name(type0 var0, type1 var1, type2 var2);
/// \relatesalso PIObject \brief declare event \"event\" with name \"name\", void name(type0 var0, type1 var1, type2 var2, type3 var3);
#define EVENT4(name, type0, var0, type1, var1, type2, var2, type3, var3) void name(type0 var0, type1 var1, type2 var2, type3 var3);
/// \relatesalso PIObject \brief EVENT is synonym of EVENT0
#define EVENT EVENT0
#define RAISE_EVENT0(src, event)
#define RAISE_EVENT1(src, event, v0)
#define RAISE_EVENT2(src, event, v0, v1)
#define RAISE_EVENT3(src, event, v0, v1, v2)
#define RAISE_EVENT4(src, event, v0, v1, v2, v3)
#define RAISE_EVENT RAISE_EVENT0
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\". \"Event\" and \"handler\" must has equal argument lists.
#define CONNECTU(src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\".
/// Event handler will be executed by \"performer\". \"Event\" and \"handler\" must has equal argument lists.
#define CONNECTU_QUEUED(src, event, dest, handler, performer)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to lambda-expression \"functor\". \"Event\" and \"functor\" must has equal argument lists.
#define CONNECTL(src, event, functor)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT0(ret, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT1(ret, type0, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT2(ret, type0, type1, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
/// \relatesalso PIObject \brief CONNECT is synonym of CONNECT0
#define CONNECT CONNECT0
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
#define WEAK_CONNECT0(ret, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
#define WEAK_CONNECT1(ret, type0, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
#define WEAK_CONNECT2(ret, type0, type1, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
#define WEAK_CONNECT3(ret, type0, type1, type2, src, event, dest, handler)
/// \relatesalso PIObject \brief connect event \"event\" from object \"src\" to event handler \"handler\" with return type \"ret\" from object \"dest\" without check of event exists
#define WEAK_CONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
/// \relatesalso PIObject \brief WEAK_CONNECT is synonym of WEAK_CONNECT0
#define WEAK_CONNECT WEAK_CONNECT0
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
#define DISCONNECT0(ret, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
#define DISCONNECT1(ret, type0, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
#define DISCONNECT2(ret, type0, type1, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
#define DISCONNECT3(ret, type0, type1, type2, src, event, dest, handler)
/// \relatesalso PIObject \brief piDisconnect event \"event\" from object \"src\" from event handler \"handler\" with return type \"ret\" from object \"dest\"
#define DISCONNECT4(ret, type0, type1, type2, type3, src, event, dest, handler)
/// \relatesalso PIObject \brief DISCONNECT is synonym of DISCONNECT0
#define DISCONNECT DISCONNECT0
/// \relatesalso PIObject \brief Returns pointer to events handler \"handler\"
#define HANDLER(handler)
#define PIOBJECT(name)
#define PIOBJECT_SUBCLASS(name)
#else
#define _PI_STR(x) #x
#define _PI_SSTR(x) _PI_STR(x)
#define LOCATION __FILE__ ":" _PI_SSTR(__LINE__)
#ifdef CC_GCC
# define __PTYPE(t) typename __PIVariantTypeInfo__<t>::PureType
#else
# define __PTYPE(t) __PIVariantTypeInfo__<t>::PureType
#endif
#define __VVALUE(t, v) v.value< __PTYPE(t) >()
//printf("base_init %s id=%d (%d) pid=%d (%d) ...\n", #name, id, eh.eh_func.size(), pid, ehp.eh_func.size());
//printf("base_init %s id=%d (%d) pid=%d (%d) ok\n", #name, id, eh.eh_func.size(), pid, ehp.eh_func.size());
//printf("parent_init %s::%s id=%d (%d) pid=%d (%d) ...\n", __classNameS().dataAscii(), #name, id, eh.eh_func.size(), pid, ehp.eh_func.size());
//printf("parent_init %s::%s id=%d (%d) pid=%d (%d) ok\n", __classNameS().dataAscii(), #name, id, eh.eh_func.size(), pid, ehp.eh_func.size());
#define PIOBJECT(name) \
protected: \
typedef name __PIObject__; \
public: \
static const PIString __classNameS() {static PIString ret = PIStringAscii(#name); return ret;} \
static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \
virtual const char * className() const {return #name;} \
virtual uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \
private: \
virtual int ptrOffset() const {name * o = (name*)100; return int(llong((PIObject*)o) - llong(o));} \
class __BaseInitializer__ { \
public: \
__BaseInitializer__() { \
uint pid = PIObject::__classNameIDS(); \
if (pid == 0) return; \
uint id = __classNameIDS(); \
PIMutexLocker ml(__meta_mutex()); \
if (__meta_data().contains(id)) return; \
__meta_data()[pid]; \
__meta_data()[id]; \
__MetaData & ehp(__meta_data()[pid]); \
__MetaData & eh(__meta_data()[id]); \
eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \
eh.addScope(__classNameS(), id); \
} \
}; \
__BaseInitializer__ __base_init__;
#define PIOBJECT_PARENT(name) \
class __ParentInitializer__ { \
public: \
__ParentInitializer__() { \
uint pid = name::__classNameIDS(); \
if (pid == 0) return; \
uint id = __classNameIDS(); \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[id]); \
if (eh.scope_id.contains(pid)) return; \
__MetaData ehp(__meta_data().value(pid)); \
eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \
eh.scope_id = ehp.scope_id; \
eh.scope_list = ehp.scope_list; \
eh.addScope(__classNameS(), id); \
} \
}; \
__ParentInitializer__ __parent_init__; \
public: \
virtual const char * parentClassName() const {return #name;} \
typedef name __Parent__; \
private:
#define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent)
#define EH_INIT0(ret, name) \
class __##name##0_Initializer__ { \
public: \
__##name##0_Initializer__() { \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \
void * fpV = fp; \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \
} \
}; \
__##name##0_Initializer__ __##name##0_init__; \
#define EH_INIT1(ret, name, a0, n0) \
class __##name##1##n0##_Initializer__ { \
public: \
__##name##1##n0##_Initializer__() { \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariant &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0); \
f.names << PIStringAscii(#n0); \
} \
}; \
__##name##1##n0##_Initializer__ __##name##1##n0##_init__; \
#define EH_INIT2(ret, name, a0, n0, a1, n1) \
class __##name##2##n0##n1##_Initializer__ { \
public: \
__##name##2##n0##n1##_Initializer__() { \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1); \
f.names << PIStringAscii(#n0) << PIStringAscii(#n1); \
} \
}; \
__##name##2##n0##n1##_Initializer__ __##name##2##n0##n1##_init__; \
#define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
class __##name##3##n0##n1##n2##_Initializer__ { \
public: \
__##name##3##n0##n1##n2##_Initializer__() { \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1) << PIObject::simplifyType(#a2); \
f.names << PIStringAscii(#n0) << PIStringAscii(#n1) << PIStringAscii(#n2); \
} \
}; \
__##name##3##n0##n1##n2##_Initializer__ __##name##3##n0##n1##n2##_init__; \
#define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
class __##name##4##n0##n1##n2##n3##_Initializer__ { \
public: \
__##name##4##n0##n1##n2##n3##_Initializer__() { \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariant &, const PIVariant &, const PIVariant &, const PIVariant &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \
__MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \
f.func_name = PIStringAscii(#name); \
f.addr = fp; \
f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \
f.types << PIObject::simplifyType(#a0) << PIObject::simplifyType(#a1) << PIObject::simplifyType(#a2) << PIObject::simplifyType(#a3); \
f.names << PIStringAscii(#n0) << PIStringAscii(#n1) << PIStringAscii(#n2) << PIStringAscii(#n3); \
} \
}; \
__##name##4##n0##n1##n2##n3##_Initializer__ __##name##4##n0##n1##n2##n3##_init__; \
#define EVENT_HANDLER0(ret, name) \
EH_INIT0(ret, name) \
static ret __stat_eh_##name##__(void * __o__) {return ((__PIObject__*)__o__)->name();} \
ret name()
#define EVENT_HANDLER1(ret, name, a0, n0) \
EH_INIT1(ret, name, a0, n0) \
static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
return ((__PIObject__*)__o__)->name(tv0);} \
ret name(a0 n0)
#define EVENT_HANDLER2(ret, name, a0, n0, a1, n1) \
EH_INIT2(ret, name, a0, n0, a1, n1) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
return ((__PIObject__*)__o__)->name(tv0, tv1);} \
ret name(a0 n0, a1 n1)
#define EVENT_HANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \
EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
__PTYPE(a2) tv2 = __VVALUE(a2, v2); \
return ((__PIObject__*)__o__)->name(tv0, tv1, tv2);} \
ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_HANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) { \
__PTYPE(a0) tv0 = __VVALUE(a0, v0); \
__PTYPE(a1) tv1 = __VVALUE(a1, v1); \
__PTYPE(a2) tv2 = __VVALUE(a2, v2); \
__PTYPE(a3) tv3 = __VVALUE(a3, v3); \
return ((__PIObject__*)__o__)->name(tv0, tv1, tv2, tv3);} \
ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#define EVENT_HANDLER EVENT_HANDLER0
#define EVENT_VHANDLER0(ret, name) \
EH_INIT0(ret, name) \
static ret __stat_eh_##name##__(void * __o__) {return ((__PIObject__*)__o__)->name();} \
virtual ret name()
#define EVENT_VHANDLER1(ret, name, a0, n0) \
EH_INIT1(ret, name, a0, n0) \
static ret __stat_eh_##name##__(void * __o__, a0 n0) {return ((__PIObject__*)__o__)->name(n0);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0));} \
virtual ret name(a0 n0)
#define EVENT_VHANDLER2(ret, name, a0, n0, a1, n1) \
EH_INIT2(ret, name, a0, n0, a1, n1) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1) {return ((__PIObject__*)__o__)->name(n0, n1);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1));} \
virtual ret name(a0 n0, a1 n1)
#define EVENT_VHANDLER3(ret, name, a0, n0, a1, n1, a2, n2) \
EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2) {return ((__PIObject__*)__o__)->name(n0, n1, n2);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2));} \
virtual ret name(a0 n0, a1 n1, a2 n2)
#define EVENT_VHANDLER4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
static ret __stat_eh_##name##__(void * __o__, a0 n0, a1 n1, a2 n2, a3 n3) {return ((__PIObject__*)__o__)->name(n0, n1, n2, n3);} \
static ret __stat_eh_v_##name##__(void * __o__, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return ((__PIObject__*)__o__)->name(__VVALUE(a0, v0), __VVALUE(a1, v1), __VVALUE(a2, v2), __VVALUE(a3, v3));} \
virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3)
#define EVENT_VHANDLER EVENT_VHANDLER0
#define EVENT0(name) EVENT_HANDLER0(void, name) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid);}
#define EVENT1(name, a0, n0) EVENT_HANDLER1(void, name, a0, n0) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0);}
#define EVENT2(name, a0, n0, a1, n1) EVENT_HANDLER2(void, name, a0, n0, a1, n1) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1);}
#define EVENT3(name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(void, name, a0, n0, a1, n1, a2, n2) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2);}
#define EVENT4(name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(void, name, a0, n0, a1, n1, a2, n2, a3, n3) {static uint eid = PIStringAscii(#name).hash(); PIObject::raiseEvent(this, eid, n0, n1, n2, n3);}
#define EVENT EVENT0
#define RAISE_EVENT0(src, event) (src)->event();
#define RAISE_EVENT1(src, event, v0) (src)->event(v0);
#define RAISE_EVENT2(src, event, v0, v1) (src)->event(v0, v1);
#define RAISE_EVENT3(src, event, v0, v1, v2) (src)->event(v0, v1, v2);
#define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3);
#define RAISE_EVENT RAISE_EVENT0
#define CONNECTU(src, event, dest, handler) PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION);
#define CONNECTU_QUEUED(src, event, dest, handler, performer) PIObject::piConnectU(src, PIStringAscii(#event), dest, dest, PIStringAscii(#handler), LOCATION, performer);
#define CONNECTL(src, event, functor) PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION);
#define CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__), 0, LOCATION);
#define CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__), 1, LOCATION);
#define CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__), 2, LOCATION);
#define CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__), 3, LOCATION);
#define CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__), 4, LOCATION);
#define CONNECT CONNECT0
#define WEAK_CONNECT0(ret, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__), 0, 0, LOCATION);
#define WEAK_CONNECT1(ret, a0, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__), 0, 1, LOCATION);
#define WEAK_CONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__), 0, 2, LOCATION);
#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__), 0, 3, LOCATION);
#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piConnect(src, PIStringAscii(#event), dest, dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__), 0, 4, LOCATION);
#define WEAK_CONNECT WEAK_CONNECT0
#define DISCONNECT0(ret, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT1(ret, a0, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT2(ret, a0, a1, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT3(ret, a0, a1, a2, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dest, handler) PIObject::piDisconnect(src, PIStringAscii(#event), dest, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dest)->__stat_eh_##handler##__));
#define DISCONNECT DISCONNECT0
#define HANDLER(handler) __stat_eh_##handler##__
#define __PIOBJECT_SIGNATURE__ 0xabcdbadc
#endif
typedef void (*Handler)(void * );
class PIP_EXPORT PIObject {
friend class PIObjectManager;
friend void dumpApplication();
typedef PIObject __PIObject__;
typedef void __Parent__;
friend class PIIntrospection;
public:
NO_COPY_CLASS(PIObject)
//! Contructs PIObject with name "name"
explicit PIObject(const PIString & name = PIString());
virtual ~PIObject();
private:
uint _signature_;
public:
//! Returns object name
PIString name() const {return property(PIStringAscii("name")).toString();}
//! Returns object class name
virtual const char * className() const {return "PIObject";}
virtual uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
static const PIString __classNameS() {return PIStringAscii("PIObject");}
static uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
//! Returns parent object class name
virtual const char * parentClassName() const {return "";}
//! Return if debug of this object is active
bool debug() const {return property(PIStringAscii("debug")).toBool();}
//! Set object name
void setName(const PIString & name) {setProperty(PIStringAscii("name"), name);}
void setName(const char * name) {setName(PIStringAscii(name));}
//! Set object debug active
void setDebug(bool debug) {setProperty(PIStringAscii("debug"), debug);}
//! Returns properties of the object
PIMap<PIString, PIVariant> properties() const;
//! Returns properties count of the object
int propertiesCount() const {return properties_.size_s();}
//! Returns property with name "name"
PIVariant property(const PIString & name) const {return properties_.value(name.hash(), Property(PIString(), PIVariant())).second;}
PIVariant property(const char * name) const {return property(PIStringAscii(name));}
//! Set property with name "name" to "value". If there is no such property in object it will be added
void setProperty(const PIString & name, const PIVariant & value) {properties_[name.hash()] = Property(name, value); propertyChanged(name);}
void setProperty(const char * name, const PIVariant & value) {setProperty(PIStringAscii(name), value);}
//! Returns if property with name "name" exists
bool isPropertyExists(const PIString & name) const {return properties_.contains(name.hash());}
bool isPropertyExists(const char * name) const {return isPropertyExists(PIStringAscii(name));}
void setThreadSafe(bool yes) {thread_safe_ = yes;}
bool isThreadSafe() const {return thread_safe_;}
bool execute(const PIString & method, const PIVector<PIVariant> & vl);
bool execute(const PIString & method) {return execute(method, PIVector<PIVariant>());}
bool execute(const PIString & method, const PIVariant & v0) {return execute(method, PIVector<PIVariant>() << v0);}
bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1) {return execute(method, PIVector<PIVariant>() << v0 << v1);}
bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return execute(method, PIVector<PIVariant>() << v0 << v1 << v2);}
bool execute(const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return execute(method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariant> & vl);
bool executeQueued(PIObject * performer, const PIString & method) {return executeQueued(performer, method, PIVector<PIVariant>());}
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0) {return executeQueued(performer, method, PIVector<PIVariant>() << v0);}
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return executeQueued(performer, method, PIVector<PIVariant>() << v0 << v1);}
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return executeQueued(performer, method, PIVector<PIVariant>() << v0 << v1 << v2);}
bool executeQueued(PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return executeQueued(performer, method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
static bool execute(PIObject * o, const PIString & method, const PIVector<PIVariant> & vl) {return o->execute(method, vl);}
static bool execute(PIObject * o, const PIString & method) {return execute(o, method, PIVector<PIVariant>());}
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0) {return execute(o, method, PIVector<PIVariant>() << v0);}
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return execute(o, method, PIVector<PIVariant>() << v0 << v1);}
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return execute(o, method, PIVector<PIVariant>() << v0 << v1 << v2);}
static bool execute(PIObject * o, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return execute(o, method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector<PIVariant> & vl) {return o->executeQueued(performer, method, vl);}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) {return executeQueued(o, performer, method, PIVector<PIVariant>());}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0);}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0 << v1);}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0 << v1 << v2);}
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariant & v0, const PIVariant & v1, const PIVariant & v2, const PIVariant & v3) {return executeQueued(o, performer, method, PIVector<PIVariant>() << v0 << v1 << v2 << v3);}
void dump(const PIString & line_prefix = PIString()) const;
PIStringList scopeList() const;
PIStringList methodsEH() const;
bool isMethodEHContains(const PIString & name) const;
PIString methodEHArguments(const PIString & name) const;
PIString methodEHFullFormat(const PIString & name) const;
PIString methodEHFromAddr(const void * addr) const;
// / Direct connect
static void piConnect(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, void * ev_h, void * e_h, int args, const char * loc);
static bool piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0);
static bool piConnectLS(PIObject * src, const PIString & sig, std::function<void()> * f, const char * loc);
template <typename INPUT, typename... TYPES>
static std::function<void()> * __newFunctor(void(*stat_handler)(void*,TYPES...), INPUT functor) {
return (std::function<void()>*)(new std::function<void(TYPES...)>(functor));
}
// / Through names and mixed
static void piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h);
static void piConnect(PIObject * src, const PIString & sig, const PIString & dest, void * ev_h);
static void piConnect(const PIString & src, const PIString & sig, const PIString & dest, void * ev_h);
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h);
static void piDisconnect(PIObject * src, const PIString & sig, PIObject * dest);
//! Disconnect object "src" from all connections with event name "sig"
static void piDisconnect(PIObject * src, const PIString & sig);
//! Disconnect object "src" from all connections, i.e. all connections where object "src" is emitter
static void piDisconnect(PIObject * src);
// / Raise events
static void raiseEvent(PIObject * sender, const uint eventID) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
__Connection i(sender->connections[j]);
if (i.eventID != eventID) continue;
if (i.functor) {
(*(i.functor))();
} else {
if (i.performer) {
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender));
} else {
bool ts = sender->thread_safe_;
if (ts) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
((void( *)(void * ))i.slot)(i.dest);
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
if (ts) i.dest_o->mutex_.unlock();
}
}
}
if (!sender->isPIObject()) break;
}
}
template <typename T0>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
__Connection i(sender->connections[j]);
if (i.eventID != eventID) continue;
if (i.functor) {
(*((std::function<void(T0)>*)i.functor))(v0);
} else {
if (i.performer) {
PIVector<PIVariant> vl;
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
} else {
bool ts = sender->thread_safe_;
if (ts) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
if (i.args_count == 0) ((void(*)(void *))i.slot)(i.dest);
else ((void(*)(void * , T0))i.slot)(i.dest, v0);
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
if (ts) i.dest_o->mutex_.unlock();
}
}
}
if (!sender->isPIObject()) break;
}
}
template <typename T0, typename T1>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
__Connection i(sender->connections[j]);
if (i.eventID != eventID) continue;
if (i.functor) {
(*((std::function<void(T0, T1)>*)i.functor))(v0, v1);
} else {
if (i.performer) {
PIVector<PIVariant> vl;
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
if (i.args_count > 1) vl << PIVariant::fromValue(v1);
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
} else {
bool ts = sender->thread_safe_;
if (ts) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
switch (i.args_count) {
case 0: ((void(*)(void *))i.slot)(i.dest); break;
case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break;
default: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break;
}
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
if (ts) i.dest_o->mutex_.unlock();
}
}
}
if (!sender->isPIObject()) break;
}
}
template <typename T0, typename T1, typename T2>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
__Connection i(sender->connections[j]);
if (i.eventID != eventID) continue;
if (i.functor) {
(*((std::function<void(T0, T1, T2)>*)i.functor))(v0, v1, v2);
} else {
if (i.performer) {
PIVector<PIVariant> vl;
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
if (i.args_count > 1) vl << PIVariant::fromValue(v1);
if (i.args_count > 2) vl << PIVariant::fromValue(v2);
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
} else {
bool ts = sender->thread_safe_;
if (ts) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
switch (i.args_count) {
case 0: ((void(*)(void *))i.slot)(i.dest); break;
case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break;
case 2: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break;
default: ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); break;
}
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
if (ts) i.dest_o->mutex_.unlock();
}
}
}
if (!sender->isPIObject()) break;
}
}
template <typename T0, typename T1, typename T2, typename T3>
static void raiseEvent(PIObject * sender, const uint eventID, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) {
for (int j = 0; j < sender->connections.size_s(); ++j) {
__Connection i(sender->connections[j]);
if (i.eventID != eventID) continue;
if (i.functor) {
(*((std::function<void(T0, T1, T2, T3)>*)i.functor))(v0, v1, v2, v3);
} else {
if (i.performer) {
PIVector<PIVariant> vl;
if (i.args_count > 0) vl << PIVariant::fromValue(v0);
if (i.args_count > 1) vl << PIVariant::fromValue(v1);
if (i.args_count > 2) vl << PIVariant::fromValue(v2);
if (i.args_count > 3) vl << PIVariant::fromValue(v3);
i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl));
} else {
bool ts = sender->thread_safe_;
if (ts) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
switch (i.args_count) {
case 0: ((void(*)(void *))i.slot)(i.dest); break;
case 1: ((void(*)(void * , T0))i.slot)(i.dest, v0); break;
case 2: ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); break;
case 3: ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); break;
default: ((void(*)(void * , T0, T1, T2, T3))i.slot)(i.dest, v0, v1, v2, v3); break;
}
if (i.dest_o->isPIObject()) {
i.dest_o->emitter_ = 0;
if (ts) i.dest_o->mutex_.unlock();
}
}
}
if (!sender->isPIObject()) break;
}
}
//! Returns PIObject* with name "name" or 0, if there is no object found
static PIObject * findByName(const PIString & name) {
PIMutexLocker _ml(mutexObjects());
piForeach (PIObject * i, PIObject::objects()) {
if (i->name() != name) continue;
return i;
}
return 0;
}
bool isPIObject() const {return isPIObject(this);}
template<typename T>
bool isTypeOf() const {
if (!isPIObject()) return false;
return scopeList().contains(T::__classNameS());
}
template<typename T>
T * cast() const {
if (!isTypeOf<T>()) return (T*)0;
return (T*)this;
}
static bool isPIObject(const PIObject * o);
static bool isPIObject(const void * o) {return isPIObject((PIObject*)o);}
template<typename T>
static bool isTypeOf(const PIObject * o) {return o->isTypeOf<T>();}
template<typename T>
static bool isTypeOf(const void * o) {return isTypeOf<T>((PIObject*)o);}
static PIString simplifyType(const char * a);
struct PIP_EXPORT __MetaFunc {
__MetaFunc(): addr(0), addrV(0) {;}
bool isNull() const {return addr == 0;}
PIString arguments() const;
PIString fullFormat() const;
void * addr;
void * addrV;
PIString func_name;
PIString type_ret;
PIString scope;
PIStringList types;
PIStringList names;
};
struct PIP_EXPORT __MetaData {
__MetaData() {scope_list << PIStringAscii("PIObject"); scope_id << PIStringAscii("PIObject").hash();}
void addScope(const PIString & s, uint shash);
PIStringList scope_list;
PISet<uint> scope_id;
PISet<const void * > eh_set;
PIMap<const void * , __MetaFunc> eh_func;
};
typedef PIPair<const void * , __MetaFunc> __EHPair;
static PIMutex & __meta_mutex();
static PIMap<uint, __MetaData> & __meta_data(); // [hash(classname)]=__MetaData
//! \brief Execute all posted events from CONNECTU_QUEUED connections
void callQueuedEvents();
//! \brief Check if any CONNECTU_QUEUED connections to this object and execute them.
//! \details This function is more optimized than \a callQueuedEvents() for objects that doesn`t
//! appears as \"performer\" target at CONNECTU_QUEUED
bool maybeCallQueuedEvents() {if (proc_event_queue) callQueuedEvents(); return proc_event_queue;}
protected:
//! Returns PIObject* which has raised an event. This value is correct only in definition of some event handler
PIObject * emitter() const {return emitter_;}
//! Virtual function executes after property with name "name" has been changed
virtual void propertyChanged(const PIString & name) {}
EVENT(deleted)
//! \events
//! \{
/** \fn void deleted()
* \brief Raise before object delete
* \note This event raised from destructor, so use only emitter() value,
* don`t try to cast deleted object to some subclass! */
//! \}
private:
struct __Connection {
__Connection(void * sl = 0, void * si = 0, const PIString & e = PIString(), PIObject * d_o = 0, void * d = 0, int ac = 0, PIObject * p = 0) {
slot = sl;
signal = si;
event = e;
eventID = e.hash();
dest_o = d_o;
dest = d;
args_count = ac;
performer = p;
functor = 0;
}
void destroy();
void * slot;
void * signal;
std::function<void()> * functor;
PIString event;
uint eventID;
PIObject * dest_o;
PIObject * performer;
void * dest;
int args_count;
};
struct __QueuedEvent {
__QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector<PIVariant> & v = PIVector<PIVariant>()) {
slot = sl;
dest = d;
dest_o = d_o;
src = s;
values = v;
}
void * slot;
void * dest;
PIObject * dest_o;
PIObject * src;
PIVector<PIVariant> values;
};
typedef PIPair<PIString, PIVariant> Property;
typedef PIPair<uint, PIPair<PIString, PIVariant> > PropertyHash;
bool findSuitableMethodV(const PIString & method, int args, int & ret_args, __MetaFunc & ret);
PIVector<__MetaFunc> findEH(const PIString & name) const;
__MetaFunc methodEH(const void * addr) const;
void updateConnectors();
void postQueuedEvent(const __QueuedEvent & e);
void * toThis() const;
virtual int ptrOffset() const {return 0;}
static PIVector<PIObject * > & objects();
static PIMutex & mutexObjects();
static void callAddrV(void * slot, void * obj, int args, const PIVector<PIVariant> & vl);
PIVector<__Connection> connections;
PIMap<uint, PIPair<PIString, PIVariant> > properties_;
PISet<PIObject * > connectors;
PIVector<__QueuedEvent> events_queue;
PIMutex mutex_, mutex_connect, mutex_queue;
PIObject * emitter_;
bool thread_safe_, proc_event_queue;
};
PIP_EXPORT void dumpApplication();
PIP_EXPORT bool dumpApplicationToFile(const PIString & path);
#endif // PIOBJECT_H