diff --git a/CMakeLists.txt b/CMakeLists.txt index d59cca2a..9c14eb2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(pip) set(pip_MAJOR 2) -set(pip_MINOR 7) -set(pip_REVISION 1) +set(pip_MINOR 8) +set(pip_REVISION 0) set(pip_SUFFIX ) set(pip_COMPANY SHS) set(pip_DOMAIN org.SHS) diff --git a/libs/main/core/piobject.cpp b/libs/main/core/piobject.cpp index 42af0a01..fa04cd78 100644 --- a/libs/main/core/piobject.cpp +++ b/libs/main/core/piobject.cpp @@ -19,6 +19,8 @@ #include "piobject.h" #include "pisysteminfo.h" +#include "pithread.h" +#include "piconditionvar.h" #ifndef FREERTOS # include "pifile.h" #endif @@ -73,6 +75,7 @@ PIString PIObject::__MetaFunc::fullFormat() const { PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), emitter_(0), thread_safe_(false), proc_event_queue(false) { + in_event_cnt = 0; setName(name); setDebug(true); mutexObjects().lock(); @@ -83,6 +86,7 @@ PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), PIObject::~PIObject() { + in_event_cnt = 0; //piCout << "delete" << this; mutexObjects().lock(); objects().removeAll(this); @@ -488,6 +492,11 @@ void PIObject::callQueuedEvents() { } +void PIObject::deleteLater() { + Deleter::instance()->post(this); +} + + bool PIObject::findSuitableMethodV(const PIString & method, int args, int & ret_args, PIObject::__MetaFunc & ret) { PIVector<__MetaFunc> ml = findEH(method); if (ml.isEmpty()) { @@ -674,3 +683,103 @@ void PIObject::__Connection::destroy() { if (functor) delete functor; functor = nullptr; } + + + + +PRIVATE_DEFINITION_START(PIObject::Deleter) + PIThread thread; + PIConditionVariable cond_var; + PIMutex cond_mutex, queue_mutex; + PIVector obj_queue; +PRIVATE_DEFINITION_END(PIObject::Deleter) + + +PIObject::Deleter::Deleter() { + //piCout << "Deleter start ..."; + stopping = started = posted = false; + CONNECTL(&(PRIVATE->thread), started, [this](){proc();}); + PRIVATE->thread.startOnce(); + while (!started) + piMSleep(1); +} + + +PIObject::Deleter::~Deleter() { + //piCout << "~Deleter ..."; + stopping = true; + PRIVATE->cond_var.notifyAll(); +#ifndef WINDOWS + while (PRIVATE->thread.isRunning()) + piMSleep(1); +#endif + deleteAll(); + //piCout << "~Deleter ok"; +} + + +PIObject::Deleter * PIObject::Deleter::instance() { + static Deleter ret; + return &ret; +} + + +void PIObject::Deleter::post(PIObject * o) { + if (!o->isPIObject()) return; + //piCout << "[Deleter] post" << o << "..."; + PRIVATE->queue_mutex.lock(); + if (!PRIVATE->obj_queue.contains(o)) + PRIVATE->obj_queue << o; + PRIVATE->queue_mutex.unlock(); + PRIVATE->cond_var.notifyAll(); + posted = true; + //piCout << "[Deleter] post" << o << "done"; +} + + +void PIObject::Deleter::proc() { + //piCout << "[Deleter] proc start"; + while (!stopping) { + //piMSleep(1); + //piCout << "[Deleter] proc wait ..."; + if (posted) { + posted = false; + started = true; + } else { + PRIVATE->cond_mutex.lock(); + started = true; + PRIVATE->cond_var.wait(PRIVATE->cond_mutex); + PRIVATE->cond_mutex.unlock(); + } + //piCout << "[Deleter] proc wait done"; + deleteAll(); + } + //piCout << "[Deleter] proc end ok"; +} + + +void PIObject::Deleter::deleteAll() { + PIVector oq; + PRIVATE->queue_mutex.lock(); + oq = PRIVATE->obj_queue; + //piCout << "[Deleter] deleteAll" << oq.size_s() << "..."; + PRIVATE->obj_queue.clear(); + PRIVATE->queue_mutex.unlock(); + piForeach (PIObject * o, oq) + deleteObject(o); +} + + +void PIObject::Deleter::deleteObject(PIObject * o) { + //piCout << "[Deleter] delete" << (uintptr_t)o << "..."; + if (o->isPIObject()) { + //piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic ..."; + while (o->isInEvent()) { + piMSleep(1); + } + //piCout << "[Deleter] delete" << (uintptr_t)o << "wait atomic done"; + if (o->isPIObject()) + delete o; + } + //piCout << "[Deleter] delete" << (uintptr_t)o << "done"; +} diff --git a/libs/main/core/piobject.h b/libs/main/core/piobject.h index cbc309a3..abfb5436 100644 --- a/libs/main/core/piobject.h +++ b/libs/main/core/piobject.h @@ -30,444 +30,9 @@ #include "pimutex.h" #include "piset.h" #include "piqueue.h" +#include "piobject_macros.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__::PureType -#else -# define __PTYPE(t) __PIVariantTypeInfo__::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) \ - STATIC_INITIALIZER_BEGIN \ - 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); \ - STATIC_INITIALIZER_END - -#define EH_INIT1(ret, name, a0, n0) \ - STATIC_INITIALIZER_BEGIN \ - 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); \ - STATIC_INITIALIZER_END - -#define EH_INIT2(ret, name, a0, n0, a1, n1) \ - STATIC_INITIALIZER_BEGIN \ - 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); \ - STATIC_INITIALIZER_END - -#define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \ - STATIC_INITIALIZER_BEGIN \ - 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); \ - STATIC_INITIALIZER_END - -#define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ - STATIC_INITIALIZER_BEGIN \ - 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); \ - STATIC_INITIALIZER_END - - -#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 { @@ -611,11 +176,15 @@ public: } else { bool ts = sender->thread_safe_; if (ts) i.dest_o->mutex_.lock(); + i.dest_o->eventBegin(); + sender->eventBegin(); i.dest_o->emitter_ = sender; ((void( *)(void * ))i.slot)(i.dest); + sender->eventEnd(); if (i.dest_o->isPIObject()) { i.dest_o->emitter_ = 0; if (ts) i.dest_o->mutex_.unlock(); + i.dest_o->eventEnd(); } } } @@ -638,12 +207,16 @@ public: } else { bool ts = sender->thread_safe_; if (ts) i.dest_o->mutex_.lock(); + i.dest_o->eventBegin(); + sender->eventBegin(); 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); + sender->eventEnd(); if (i.dest_o->isPIObject()) { i.dest_o->emitter_ = 0; if (ts) i.dest_o->mutex_.unlock(); + i.dest_o->eventEnd(); } } } @@ -666,15 +239,19 @@ public: } else { bool ts = sender->thread_safe_; if (ts) i.dest_o->mutex_.lock(); + i.dest_o->eventBegin(); + sender->eventBegin(); 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; } + sender->eventEnd(); if (i.dest_o->isPIObject()) { i.dest_o->emitter_ = 0; if (ts) i.dest_o->mutex_.unlock(); + i.dest_o->eventEnd(); } } } @@ -698,6 +275,8 @@ public: } else { bool ts = sender->thread_safe_; if (ts) i.dest_o->mutex_.lock(); + i.dest_o->eventBegin(); + sender->eventBegin(); i.dest_o->emitter_ = sender; switch (i.args_count) { case 0: ((void(*)(void *))i.slot)(i.dest); break; @@ -705,9 +284,11 @@ public: 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; } + sender->eventEnd(); if (i.dest_o->isPIObject()) { i.dest_o->emitter_ = 0; if (ts) i.dest_o->mutex_.unlock(); + i.dest_o->eventEnd(); } } } @@ -732,6 +313,8 @@ public: } else { bool ts = sender->thread_safe_; if (ts) i.dest_o->mutex_.lock(); + i.dest_o->eventBegin(); + sender->eventBegin(); i.dest_o->emitter_ = sender; switch (i.args_count) { case 0: ((void(*)(void *))i.slot)(i.dest); break; @@ -740,9 +323,11 @@ public: 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; } + sender->eventEnd(); if (i.dest_o->isPIObject()) { i.dest_o->emitter_ = 0; if (ts) i.dest_o->mutex_.unlock(); + i.dest_o->eventEnd(); } } } @@ -793,6 +378,7 @@ public: 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); @@ -803,17 +389,22 @@ public: }; typedef PIPair __EHPair; - static PIMutex & __meta_mutex(); - static PIMap & __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. + //! \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;} + //! \brief Mark object to delete + //! \details On first call background thread started to delete objects. + //! Each object deletes when it`s outside from any events and hadlers. + void deleteLater(); + + static PIMutex & __meta_mutex(); + static PIMap & __meta_data(); // [hash(classname)]=__MetaData + protected: //! Returns PIObject* which has raised an event. This value is correct only in definition of some event handler @@ -835,6 +426,7 @@ protected: //! \} 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; @@ -858,6 +450,7 @@ private: void * dest; int args_count; }; + struct __QueuedEvent { __QueuedEvent(void * sl = 0, void * d = 0, PIObject * d_o = 0, PIObject * s = 0, const PIVector & v = PIVector()) { slot = sl; @@ -872,6 +465,21 @@ private: PIObject * src; PIVector values; }; + + class Deleter { + public: + Deleter(); + ~Deleter(); + static Deleter * instance(); + void post(PIObject * o); + private: + void proc(); + void deleteAll(); + void deleteObject(PIObject * o); + std::atomic_bool stopping, started, posted; + PRIVATE_DECLARATION(PIP_EXPORT) + }; + typedef PIPair Property; typedef PIPair > PropertyHash; @@ -880,6 +488,9 @@ private: __MetaFunc methodEH(const void * addr) const; void updateConnectors(); void postQueuedEvent(const __QueuedEvent & e); + void eventBegin() {in_event_cnt++;} + void eventEnd () {in_event_cnt--;} + bool isInEvent() const {return in_event_cnt > 0;} void * toThis() const; virtual int ptrOffset() const {return 0;} @@ -895,6 +506,7 @@ private: PIMutex mutex_, mutex_connect, mutex_queue; PIObject * emitter_; bool thread_safe_, proc_event_queue; + std::atomic_int in_event_cnt; }; diff --git a/libs/main/core/piobject_macros.h b/libs/main/core/piobject_macros.h new file mode 100644 index 00000000..c4c5da43 --- /dev/null +++ b/libs/main/core/piobject_macros.h @@ -0,0 +1,464 @@ +/*! \file piobject.h + * \brief Base object + * + * This file declare PIObject class and associated macros +*/ +/* + PIP - Platform Independent Primitives + Macros for PIObject + 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 . +*/ + +#ifndef PIOBJECT_MACROS_H +#define PIOBJECT_MACROS_H + +//#include "piobject_macros.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__::PureType +#else +# define __PTYPE(t) __PIVariantTypeInfo__::PureType +#endif +#define __VVALUE(t, v) v.value< __PTYPE(t) >() + + +#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) \ + STATIC_INITIALIZER_BEGIN \ + 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); \ + STATIC_INITIALIZER_END + +#define EH_INIT1(ret, name, a0, n0) \ + STATIC_INITIALIZER_BEGIN \ + 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); \ + STATIC_INITIALIZER_END + +#define EH_INIT2(ret, name, a0, n0, a1, n1) \ + STATIC_INITIALIZER_BEGIN \ + 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); \ + STATIC_INITIALIZER_END + +#define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \ + STATIC_INITIALIZER_BEGIN \ + 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); \ + STATIC_INITIALIZER_END + +#define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ + STATIC_INITIALIZER_BEGIN \ + 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); \ + STATIC_INITIALIZER_END + + +#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 + + +#endif // PIOBJECT_MACROS_H diff --git a/main.cpp b/main.cpp index 709bbb77..1165af51 100644 --- a/main.cpp +++ b/main.cpp @@ -1,9 +1,79 @@ #include "pip.h" + +#define REGISTER_CNT (__COUNTER__) +#define REGISTER_V_STREAM_INTERNAL(T, C) \ + class _VariantRegistrator_##C##__ { \ + public: \ + _VariantRegistrator_##C##__() { \ + __VariantFunctionsBase__ * f = __VariantFunctions__().instance(); \ + __VariantFunctionsBase__::registered()[f->hash()] = f; \ + } \ + }; \ + _VariantRegistrator_##C##__ __registrator_##C##__; + + +#define REGISTER_V_STREAM_INTERNAL_W(T, C) REGISTER_V_STREAM_INTERNAL(T, C) +#define REGISTER_V_STREAM(T) REGISTER_V_STREAM_INTERNAL_W(T, __COUNTER__) + + + + +class Send: public PIObject { + PIOBJECT(Send) +public: + Send() {piCout << "Send";} + ~Send() {piCout << "~Send";} + EVENT1(ev, PIObject * , o); +}; + + +class Recv: public PIObject { + PIOBJECT(Recv) +public: + Recv() {piCout << "Recv";} + ~Recv() {piCout << "~Recv";} + EVENT_HANDLER1(void, eh, PIObject * , o) { + piCout << "eh ..." << o; + o->deleteLater(); + piMSleep(1000); + piCout << "eh ok"; + } +}; + + +Send * s = new Send(); +Recv * r = new Recv(); + +#include "piconditionvar.h" int main() { - versionCompare("",""); - PICloudServer s("127.0.0.1:10101"); - s.startThreadedRead(); - piSleep(10); + + CONNECTU(s, ev, r, eh); + s->ev(r); + r->deleteLater(); + s->deleteLater(); + piMSleep(1500); + //s->deleteLater(); + //delete o; + //eth.dump(); + //versionCompare("",""); + //PICloudServer s("127.0.0.1:10101"); + //s.startThreadedRead(); + piMSleep(10); + + /*PIMutex m; + PIConditionVariable var; + + PIThread::runOnce([&](){ + piCout << "wait ..."; + m.lock(); + var.wait(m); + m.unlock(); + piCout << "wait done"; + }); + + piMSleep(100); + var.notifyAll();*/ + return 0; }