518 lines
20 KiB
C++
518 lines
20 KiB
C++
/*! \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"
|
|
#include "piobject_macros.h"
|
|
|
|
|
|
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->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();
|
|
}
|
|
}
|
|
}
|
|
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->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();
|
|
}
|
|
}
|
|
}
|
|
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->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();
|
|
}
|
|
}
|
|
}
|
|
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->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;
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
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->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;
|
|
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;
|
|
}
|
|
sender->eventEnd();
|
|
if (i.dest_o->isPIObject()) {
|
|
i.dest_o->emitter_ = 0;
|
|
if (ts) i.dest_o->mutex_.unlock();
|
|
i.dest_o->eventEnd();
|
|
}
|
|
}
|
|
}
|
|
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;
|
|
|
|
//! \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;}
|
|
|
|
//! \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<uint, __MetaData> & __meta_data(); // [hash(classname)]=__MetaData
|
|
|
|
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;
|
|
};
|
|
|
|
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<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 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;}
|
|
|
|
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;
|
|
std::atomic_int in_event_cnt;
|
|
|
|
};
|
|
|
|
|
|
PIP_EXPORT void dumpApplication();
|
|
PIP_EXPORT bool dumpApplicationToFile(const PIString & path);
|
|
|
|
#endif // PIOBJECT_H
|