git-svn-id: svn://db.shs.com.ru/pip@478 12ceb7fc-bf1f-11e4-8940-5bc7170c53b5

This commit is contained in:
2017-04-26 22:08:42 +00:00
parent 0e50a87317
commit 51f801c83b
4 changed files with 165 additions and 182 deletions

View File

@@ -72,7 +72,7 @@ PIString PIObject::__EHFunc::fullFormat() const {
}
PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), emitter_(0), thread_safe_(false) {
PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), emitter_(0), thread_safe_(false), proc_event_queue(false) {
piMonitor.objects++;
//__PIVariantInitBuiltin__();
setName(name);
@@ -225,7 +225,7 @@ void PIObject::piConnect(PIObject * src, const PIString & sig, PIObject * dest_o
}
bool PIObject::piConnectU(PIObject * src, const PIString & ename, PIObject * dest_o, void * dest, const PIString & hname, const char * loc) {
bool PIObject::piConnectU(PIObject * src, const PIString & ename, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer) {
if (src == 0 || dest_o == 0 || dest == 0) return false;
if (!src->isPIObject()) {
piCout << "[piConnectU] \"" << ename << "\" -> \"" << hname << "\" error: source object is not PIObject! (" << loc << ")";
@@ -249,13 +249,14 @@ bool PIObject::piConnectU(PIObject * src, const PIString & ename, PIObject * des
}
void * addr_src(0), * addr_dest(0);
int args(0);
bool que = (performer != 0);
piForeachC (__EHFunc & fs, m_src) {
if (addr_src != 0) break;
piForeachC (__EHFunc & fd, m_dest) {
if (addr_src != 0) break;
if (fs.arguments().startsWith(fd.arguments()) || fd.arguments().isEmpty()) {
addr_src = fs.addr;
addr_dest = fd.addr;
addr_dest = que ? fd.addrV : fd.addr;
args = fd.names.size_s();
}
}
@@ -266,7 +267,8 @@ bool PIObject::piConnectU(PIObject * src, const PIString & ename, PIObject * des
return false;
}
//piCout << "connect" << ename << "->" << hname << "with" << args << "args";
src->connections << PIObject::Connection(addr_dest, addr_src, ename, dest_o, dest, args);
src->connections << PIObject::Connection(addr_dest, addr_src, ename, dest_o, dest, args, performer);
if (que) performer->proc_event_queue = true;
dest_o->connectors << src;
return true;
}
@@ -354,6 +356,13 @@ void PIObject::updateConnectors() {
}
void PIObject::postQueuedEvent(const PIObject::QueuedEvent & e) {
mutex_queue.lock();
events_queue << e;
mutex_queue.unlock();
}
PIMutex & PIObject::__meta_mutex() {
static PIMutex ret;
return ret;
@@ -366,6 +375,28 @@ PIMap<PIString, PIObject::__MetaData> & PIObject::__meta_data() {
}
void PIObject::callQueuedEvents() {
mutex_queue.lock();
PIVector<QueuedEvent> qe = events_queue;
events_queue.clear();
mutex_queue.unlock();
piForeachC (QueuedEvent & e, qe) {
if (e.dest_o->thread_safe_) e.dest_o->mutex_.lock();
e.dest_o->emitter_ = e.src;
switch (e.values.size_s()) {
case 0: ((void(*)(void *))e.slot)(e.dest); break;
case 1: ((void(*)(void * , const PIVariant & ))e.slot)(e.dest, e.values[0]); break;
case 2: ((void(*)(void * , const PIVariant & , const PIVariant & ))e.slot)(e.dest, e.values[0], e.values[1]); break;
case 3: ((void(*)(void * , const PIVariant & , const PIVariant & , const PIVariant & ))e.slot)(e.dest, e.values[0], e.values[1], e.values[2]); break;
case 4: ((void(*)(void * , const PIVariant & , const PIVariant & , const PIVariant & , const PIVariant & ))e.slot)(e.dest, e.values[0], e.values[1], e.values[2], e.values[3]); break;
default: break;
}
e.dest_o->emitter_ = 0;
if (e.dest_o->thread_safe_) e.dest_o->mutex_.unlock();
}
}
PIVector<PIObject * > & PIObject::objects() {
static PIVector<PIObject * > ret;
return ret;

View File

@@ -29,6 +29,7 @@
#include "pivariant.h"
#include "pimutex.h"
#include "piset.h"
#include "piqueue.h"
#ifdef DOXYGEN
@@ -109,6 +110,10 @@
/// \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 event handler \"handler\" with return type \"ret\" from object \"dest\" with check of event and handler exists
#define CONNECT0(ret, src, event, dest, handler)
@@ -421,6 +426,7 @@
#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 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);
@@ -556,7 +562,7 @@ public:
// / 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 & ename, PIObject * dest_o, void * dest, const PIString & hname, const char * loc);
static bool piConnectU(PIObject * src, const PIString & ename, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0);
// / Through names and mixed
static void piConnect(const PIString & src, const PIString & sig, void * dest, void * ev_h);
@@ -578,12 +584,15 @@ public:
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]);
if (i.event != event) continue;
//piCout << uint(i.dest) << uint(i.dest_o);
if (sender->thread_safe_) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
((void( *)(void * ))i.slot)(i.dest);
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
if (i.performer) {
i.performer->postQueuedEvent(QueuedEvent(i.slot, i.dest, i.dest_o, sender));
} else {
if (sender->thread_safe_) i.dest_o->mutex_.lock();
i.dest_o->emitter_ = sender;
((void( *)(void * ))i.slot)(i.dest);
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
}
}
@@ -592,12 +601,18 @@ public:
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]);
if (i.event != event) continue;
if (sender->thread_safe_) 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);
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
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 {
if (sender->thread_safe_) 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);
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
}
}
template <typename T0, typename T1>
@@ -605,15 +620,22 @@ public:
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]);
if (i.event != event) continue;
if (sender->thread_safe_) 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.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 {
if (sender->thread_safe_) 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;
}
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
}
template <typename T0, typename T1, typename T2>
@@ -621,16 +643,24 @@ public:
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]);
if (i.event != event) continue;
if (sender->thread_safe_) 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.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 {
if (sender->thread_safe_) 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;
}
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
}
template <typename T0, typename T1, typename T2, typename T3>
@@ -638,17 +668,26 @@ public:
for (int j = 0; j < sender->connections.size_s(); ++j) {
Connection & i(sender->connections[j]);
if (i.event != event) continue;
if (sender->thread_safe_) 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.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 {
if (sender->thread_safe_) 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;
}
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
i.dest_o->emitter_ = 0;
if (sender->thread_safe_) i.dest_o->mutex_.unlock();
}
}
@@ -754,9 +793,13 @@ public:
PIMap<const void * , __EHFunc> eh_func;
};
typedef PIPair<const void * , __EHFunc> __EHPair;
static PIMutex & __meta_mutex();
static PIMap<PIString, __MetaData> & __meta_data(); // [classname]=__MetaData
void callQueuedEvents();
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
@@ -764,8 +807,7 @@ protected:
//! Virtual function executes after property with name "name" has been changed
virtual void propertyChanged(const PIString & name) {}
EVENT(deleted)
//! \events
@@ -780,36 +822,53 @@ 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) {
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;
dest_o = d_o;
dest = d;
args_count = ac;
performer = p;
}
void * slot;
void * signal;
PIString event;
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;
PIVector<__EHFunc> findEH(const PIString & name) const;
__EHFunc methodEH(const void * addr) const;
void updateConnectors();
PIVector<Connection> connections;
typedef PIPair<PIString, PIVariant> Property;
PIMap<PIString, PIVariant> properties_;
void postQueuedEvent(const QueuedEvent & e);
static PIVector<PIObject * > & objects();
PIVector<Connection> connections;
PIMap<PIString, PIVariant> properties_;
PISet<PIObject * > connectors;
PIMutex mutex_, mutex_connect;
PIVector<QueuedEvent> events_queue;
PIMutex mutex_, mutex_connect, mutex_queue;
PIObject * emitter_;
bool thread_safe_;
bool thread_safe_, proc_event_queue;
};