diff --git a/CMakeLists.txt b/CMakeLists.txt index 99ddf30a..431aabd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,7 @@ set(PIP_UTILS 1) if(LIBPROJECT) set(PIP_UTILS ${UTILS}) endif() +set(CMAKE_CXX_STANDARD 11) # Basic @@ -40,13 +41,13 @@ macro(gather_src DIR CPP H H_P) list(APPEND ${H_P} ${PHS}) endmacro() -set(PIP_SRC_MAIN "src_main") -set(PIP_SRC_CRYPT "src_crypt") -set(PIP_SRC_COMPRESS "src_compress") -set(PIP_SRC_USB "src_usb") -set(PIP_SRC_FFTW "src_fftw") -set(PIP_SRC_OPENCL "src_opencl") -set(PIP_SRC_IO_UTILS "src_io_utils") +set(PIP_SRC_MAIN "src_main") +set(PIP_SRC_CRYPT "src_crypt") +set(PIP_SRC_COMPRESS "src_compress") +set(PIP_SRC_USB "src_usb") +set(PIP_SRC_FFTW "src_fftw") +set(PIP_SRC_OPENCL "src_opencl") +set(PIP_SRC_IO_UTILS "src_io_utils") set(PIP_SRC_CONCURRENT "src_concurrent") set(PIP_SRC_DIRS "src_main" "src_crypt" "src_compress" "src_usb" "src_fftw" "src_opencl" "src_io_utils" "src_concurrent") set(PIP_LIBS_TARGETS pip) diff --git a/main.cpp b/main.cpp index ff3874eb..02a10607 100644 --- a/main.cpp +++ b/main.cpp @@ -1,13 +1,479 @@ #include "pip.h" -void test() { - piCout << "test"; + +template +class PIHash { + //template friend PIByteArray & operator >>(PIByteArray & s, PIHash & v); + //template friend PIByteArray & operator <<(PIByteArray & s, const PIHash & v); +public: + PIHash() {;} + PIHash(const PIHash & other) {*this = other;} + virtual ~PIHash() {;} + + PIHash & operator =(const PIHash & other) { + if (this == &other) return *this; + clear(); + pih_content = other.pih_content; + return *this; + } + + typedef T mapped_type; + typedef Key key_type; + typedef PIPair value_type; +/* + class iterator { + friend class PIHash; + private: + iterator(const PIHash * v, ssize_t p): parent(v), pos(p) {} + const PIHash * parent; + ssize_t pos; + public: + iterator(): parent(0), pos(0) {} + const Key & key() const {return const_cast * >(parent)->_key(pos);} + T & value() {return const_cast * >(parent)->_value(pos);} + void operator ++() {++pos;} + void operator ++(int) {++pos;} + void operator --() {--pos;} + void operator --(int) {--pos;} + bool operator ==(const iterator & it) const {return (pos == it.pos);} + bool operator !=(const iterator & it) const {return (pos != it.pos);} + }; + + class reverse_iterator { + friend class PIHash; + private: + reverse_iterator(const PIHash * v, ssize_t p): parent(v), pos(p) {} + const PIHash * parent; + ssize_t pos; + public: + reverse_iterator(): parent(0), pos(0) {} + const Key & key() const {return const_cast * >(parent)->_key(pos);} + T & value() const {return const_cast * >(parent)->_value(pos);} + void operator ++() {--pos;} + void operator ++(int) {--pos;} + void operator --() {++pos;} + void operator --(int) {++pos;} + bool operator ==(const reverse_iterator & it) const {return (pos == it.pos);} + bool operator !=(const reverse_iterator & it) const {return (pos != it.pos);} + }; +*/ + class const_iterator { + friend class PIHash; + private: + const_iterator(const PIHash * v, ssize_t p): parent(v), pos(p), bpos(0) { + if (pos == 0) { + pos = -1; + nextPos(); + } + } + void nextPos() { + while (++pos < parent->pih_content.size_s()) { + if (!parent->pih_content[pos].isEmpty()) + return; + } + } + const PIHash * parent; + ssize_t pos, bpos; + public: + const_iterator(): parent(0), pos(0) {} + //const value_type operator *() const {return parent->_pair(pos);} + //const value_type* operator ->() const {cval = parent->_pair(pos); return &cval;} + const Key & key() const {return const_cast * >(parent)->pih_content[pos][bpos].key;} + const T & value() const {return const_cast * >(parent)->pih_content[pos][bpos].value;} + void operator ++() { + if (pos < parent->pih_content.size_s()) { + if (bpos >= parent->pih_content[pos].size_s() - 1) { + bpos = 0; + nextPos(); + } else + ++bpos; + } else { + bpos = 0; + ++pos; + } + printf(" ++: %d %d\n", pos, bpos); + } + //void operator ++(int) {++pos;} + void operator --() { + --pos; + } + //void operator --(int) {--pos;} + bool operator ==(const const_iterator & it) const {return (pos == it.pos && bpos == it.bpos);} + bool operator !=(const const_iterator & it) const {return !(*this == it);} + mutable value_type cval; + }; +/* + class const_reverse_iterator { + friend class PIHash; + private: + const_reverse_iterator(const PIHash * v, ssize_t p): parent(v), pos(p) {} + const PIHash * parent; + ssize_t pos; + public: + const_reverse_iterator(): parent(0), pos(0) {} + const value_type operator *() const {return parent->_pair(pos);} + const value_type* operator ->() const {cval = parent->_pair(pos); return &cval;} + void operator ++() {--pos;} + void operator ++(int) {--pos;} + void operator --() {++pos;} + void operator --(int) {++pos;} + bool operator ==(const const_reverse_iterator & it) const {return (pos == it.pos);} + bool operator !=(const const_reverse_iterator & it) const {return (pos != it.pos);} + mutable value_type cval; + }; +*/ + //iterator begin() {return iterator(this, 0);} + //iterator end() {return iterator(this, size());} + const_iterator begin() const {return const_iterator(this, 0);} + const_iterator end() const {return const_iterator(this, size());} + const_iterator constBegin() const {return const_iterator(this, 0);} + const_iterator constEnd() const {return const_iterator(this, size());} + //reverse_iterator rbegin() {return reverse_iterator(this, size() - 1);} + //reverse_iterator rend() {return reverse_iterator(this, -1);} + //const_reverse_iterator rbegin() const {return const_reverse_iterator(this, size() - 1);} + //const_reverse_iterator rend() const {return const_reverse_iterator(this, -1);} + //const_reverse_iterator constRbegin() const {return const_reverse_iterator(this, size() - 1);} + //const_reverse_iterator constRend() const {return const_reverse_iterator(this, -1);} + + size_t size() const {return pih_content.size();} + int size_s() const {return pih_content.size_s();} + size_t length() const {return pih_content.size();} + size_t capacity() const {return pih_content.size();} + bool isEmpty() const {return (pih_content.size() == 0);} + + T & operator [](const Key & key) { + if (pih_content.isEmpty()) _rehash(1); + uint k = piHash(key); + int i = _index(k); + if (i < pih_content.size_s()) { + PIVector & hv(pih_content[i]); + if (hv.size_s() == 1) { + if (hv[0].key == k) + return hv[0].value; + } + for (int j = 0; j < hv.size_s(); ++j) + if (hv[j].key == k) + return hv[j].value; + } + if (pih_content[i].size_s() >= 3) + _rehash(pih_content.size_s() * 2); + i = _index(k); + pih_content[i] << HashEntry(k); + return pih_content[i].back().value; + } + const T operator [](const Key & key) const {return value(key);} + T & at(const Key & key) {return (*this)[key];} + const T at(const Key & key) const {return (*this)[key];} + + PIHash & operator <<(const PIHash & other) { + if (other.isEmpty()) return *this; + for (int i = 0; i < other.pih_content.size_s(); ++i) + for (int j = 0; j < other.pih_content[i].size_s(); ++j) + insert(other.pih_content[i][j].key, other.pih_content[i][j].value); + return *this; + } + + bool operator ==(const PIHash & t) const {return (pih_content == t.pih_content);} + bool operator !=(const PIHash & t) const {return (pih_content != t.pih_content);} + bool contains(const Key & key) const { + bool f(false); + _find(key, f); + return f; + } + + PIHash & reserve(size_t new_size) {_rehash(new_size); return *this;} + + PIHash & remove(const Key & key) { + uint k = piHash(key); + int i = _index(k); + if (i >= pih_content.size_s()) return *this; + PIVector & hv(pih_content[i]); + for (int j = 0; j < hv.size_s(); ++j) + if (hv[j].key == k) { + hv.remove(j); + --j; + } + return *this; + } + PIHash & erase(const Key & key) {return remove(key);} + PIHash & clear() {pih_content.clear(); return *this;} + + void swap(PIHash & other) { + piSwapBinary > >(pih_content, other.pih_content); + } + + PIHash & insert(const Key & key, const T & value) { + (*this)[key] = value; + return *this; + } + const T value(const Key & key, const T & default_ = T()) const { + uint k = piHash(key); + int i = _index(k); + if (i >= pih_content.size_s()) return default_; + const PIVector & hv(pih_content[i]); + for (int j = 0; j < hv.size_s(); ++j) + if (hv[j].key == k) + return hv[j].value; + return default_; + } + PIVector values() const { + PIVector ret; + for (int i = 0; i < pih_content.size_s(); ++i) + for (int j = 0; j < pih_content[i].size_s(); ++j) + ret << pih_content[i][j].value; + return ret; + } + /*Key key(const T & value_, const Key & default_ = Key()) const { + for (int i = 0; i < pih_content.size_s(); ++i) + for (int j = 0; j < pih_content[i].size_s(); ++j) + if (pih_content[i][j].value == value_) + return pih_content[i][j].key; + return default_; + } + PIVector keys() const { + PIVector ret; + for (int i = 0; i < pih_content.size_s(); ++i) + for (int j = 0; j < pih_content[i].size_s(); ++j) + ret << pih_content[i][j].key; + return ret; + }*/ + + /*void dump() { + piCout << "PIHash" << size() << "entries" << PICoutManipulators::NewLine << "content:"; + for (size_t i = 0; i < pih_content.size(); ++i) + piCout << PICoutManipulators::Tab << i << ":" << pih_content[i]; + piCout << "index:"; + for (size_t i = 0; i < pim_index.size(); ++i) + piCout << PICoutManipulators::Tab << i << ":" << pim_index[i].key << "->" << pim_index[i].index; + }*/ + +protected: + struct HashEntry { + HashEntry(uint k = 0, const T & v = T()): key(k), value(v) {;} + uint key; + T value; + bool operator ==(const HashEntry & s) const {return key == s.key;} + bool operator !=(const HashEntry & s) const {return key != s.key;} + bool operator <(const HashEntry & s) const {return key < s.key;} + bool operator >(const HashEntry & s) const {return key > s.key;} + }; + /*template friend PIByteArray & operator >>(PIByteArray & s, PIDeque::HashEntry> & v); + template friend PIByteArray & operator <<(PIByteArray & s, const PIDeque::HashEntry> & v); + + const value_type _pair(ssize_t index) const { + if (index < 0 || index >= pim_index.size_s()) + return value_type(); + //piCout << "_pair" << index << pim_index[index].index; + return value_type(pim_index[index].key, pih_content[pim_index[index].index]); + } + Key & _key(ssize_t index) {return pim_index[index].key;} + T & _value(ssize_t index) {return pih_content[pim_index[index].index];}*/ + + inline size_t asize(size_t s) { + if (s == 0) return 0; + if (pih_content.size() + pih_content.size() >= s && pih_content.size() < s) + return pih_content.size() + pih_content.size(); + ssize_t t = 0, s_ = s - 1; + while (s_ >> t) ++t; + return (1 << t); + } + int _index(const uint & k) const { + return k % pih_content.size_s(); + } + void _rehash(int ns) { + ns = asize(ns); + if (pih_content.size_s() == ns) return; + PIVector > nhc; + nhc.resize(ns); + for (int i = 0; i < pih_content.size_s(); ++i) { + for (int j = 0; j < pih_content[i].size_s(); ++j) { + HashEntry & e(pih_content[i][j]); + int ni = e.key % ns; + nhc[ni] << e; + } + } + pih_content.swap(nhc); + } + + PIVector > pih_content; +}; + + +template +inline PICout operator <<(PICout s, const PIHash & v) { + s.space(); + s.setControl(0, true); + s << "{"; + bool first = true; + for (typename PIHash::const_iterator i = v.begin(); i != v.end(); ++i) { + if (!first) + s << ", "; + first = false; + s << i.key() << ": " << i.value(); + } + s << "}"; + s.restoreControl(); + return s; } + +struct HS { + HS() {i = 0; b0 = b1 = false;} + PIString str; + int i; + bool b0, b1; +}; +PICout operator <<(const PICout & s, const HS & v) {s << v.str << ", i =" << v.i << ", b =" << v.b0 << v.b1; return s;} + + + + +#include + +typedef PIVector MyType; +REGISTER_VARIANT(MyType) + + +class A: public PIObject { + PIOBJECT(A) +public: + EVENT1(e1, MyType, v) +}; + + +class B: public PIObject { + PIOBJECT(B) +public: + EVENT_HANDLER1(void, h1, MyType, v) {piCout << "handler h1" << v;} +}; + + + int main() { - PIThread::runOnce([](){ while(1) piCout << "thread1"; }); - PIThread::runOnce([](){ while(1) piCout << "thread2"; }); - PIThread::runOnce([](){ while(1) piCout << "thread3"; }); - piMSleep(1); + PIThread thread([](){piCout << "thread";}, true, 100); + piMSleep(2000); + return 0; + + PITimer timer([](){piCout << "timer";}); + //t.setSlot(test); + timer.addDelimiter(5, [](void * d){piCout << "delim 5";}); + timer.addDelimiter(2, [](){piCout << "delim 2";}); + timer.start(100); + piMSleep(2000); + + A a; + B b; + CONNECTU_QUEUED(&a, e1, &b, h1, &b); + a.e1(PIVector() << 1 << 2); + b.callQueuedEvents(); + + + return 0; + + /*for (int i = 0; i < 0x2; ++i) { + PIByteArray ba, ba2; + writeOInt(ba, i); ba2 = ba; + uint u = readOInt(ba2); + piCout << "p =" << i << ", d =" << ba.toHex() << ", u =" << u; + } + for (int i = 0x7e; i < 0x82; ++i) { + PIByteArray ba, ba2; + writeOInt(ba, i); ba2 = ba; + uint u = readOInt(ba2); + piCout << "p =" << i << ", d =" << ba.toHex() << ", u =" << u; + } + for (int i = 0x3ffe; i < 0x4002; ++i) { + PIByteArray ba, ba2; + writeOInt(ba, i); ba2 = ba; + uint u = readOInt(ba2); + piCout << "p =" << i << ", d =" << ba.toHex() << ", u =" << u; + } + for (int i = 0x1ffffe; i < 0x200002; ++i) { + PIByteArray ba, ba2; + writeOInt(ba, i); ba2 = ba; + uint u = readOInt(ba2); + piCout << "p =" << i << ", d =" << ba.toHex() << ", u =" << u; + }*/ + HS hs; + hs.str = "123"; + hs.i = 321; + hs.b1 = true; + piCout << hs; + PIByteArray ba; + { + PIChunkStream cs(PIChunkStream::Version_2); + cs.add(1, hs.str).add(2, hs.i).add(3, hs.b0).add(4, hs.b1); + ba = cs.data(); + } + hs = HS(); + piCout << ba.size() << ba.toHex(); + piCout << hs; + { + PIChunkStream cs(ba); + cs.readAll(); + cs.get(1, hs.str).get(2, hs.i).get(3, hs.b0).get(4, hs.b1); + } + piCout << hs; + + return 0; + + PIConnection con; + PIString _str = "[connection]\ndevice.d = ser://COM2:9600\n"; + con.configureFromString(&_str); + con.start(); + PISerial * s = con.deviceByName("d")->cast(); + while (1) { + piMSleep(500); + piCout << s; + if (s) + piCout << s->isOpened(); + } + return 0; + + PIHash h; + h["1"] = "x"; + h["2"] = "bbb"; + h["3"] = "bbc"; + h["4"] = "aaa"; + h["5"] = "123"; + h["6"] = "321"; + h["7"] = "aaa"; + h["7"] = "aaa!!!!!"; + piCout << h.size() << h.capacity(); + //h.reserve(64); + //piCout << h.keys() << h.values(); + //piCout << (1 << 2); + PIHash h2; + PIMap m2; + PIString prefix = "1234567890"; + PITimeMeasurer tm; + double el = 0.; + + tm.reset(); + for (int i=0; i<10000; ++i) { + h2[prefix + PIString::fromNumber(i)+"1234567890"] = PIString::fromNumber(randomi()); + } + el = tm.elapsed_m(); piCout << el << h2.capacity(); + + tm.reset(); + for (int i=0; i<10000; ++i) { + m2[prefix + PIString::fromNumber(i)+"1234567890"] = PIString::fromNumber(randomi()); + } + el = tm.elapsed_m(); piCout << el; + piCout << "*********"; + + PIString _s; + tm.reset(); + for (int i=10000; i>=0; --i) { + _s = h2.value(prefix + PIString::fromNumber(i)+"1234567890"); + } + el = tm.elapsed_m(); piCout << el << h2.capacity(); + + tm.reset(); + for (int i=10000; i>=0; --i) { + _s = m2.value(prefix + PIString::fromNumber(i)+"1234567890"); + } + el = tm.elapsed_m(); piCout << el; + return 0; } diff --git a/src_main/core/piobject.cpp b/src_main/core/piobject.cpp index 66d9fccb..03074e85 100755 --- a/src_main/core/piobject.cpp +++ b/src_main/core/piobject.cpp @@ -273,22 +273,22 @@ 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, PIObject * performer) { +bool PIObject::piConnectU(PIObject * src, const PIString & sig, 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 << ")"; + piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: source object is not PIObject! (" << loc << ")"; return false; } if (!dest_o->isPIObject()) { - piCout << "[piConnectU] \"" << ename << "\" -> \"" << hname << "\" error: destination object is not PIObject! (" << loc << ")"; + piCout << "[piConnectU] \"" << sig << "\" -> \"" << hname << "\" error: destination object is not PIObject! (" << loc << ")"; return false; } PIMutexLocker ml(__meta_mutex()); PIMutexLocker mls(src->mutex_connect); PIMutexLocker mld(dest_o->mutex_connect, src != dest_o); - PIVector<__MetaFunc> m_src = src->findEH(ename), m_dest = dest_o->findEH(hname); + PIVector<__MetaFunc> m_src = src->findEH(sig), m_dest = dest_o->findEH(hname); if (m_src.isEmpty()) { - piCout << "[piConnectU] Error: can`t find event \"" << ename << "\" in class \"" << src->className() << "\"! (" << loc << ")"; + piCout << "[piConnectU] Error: can`t find event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")"; return false; } if (m_dest.isEmpty()) { @@ -310,11 +310,11 @@ bool PIObject::piConnectU(PIObject * src, const PIString & ename, PIObject * des } } if (addr_src == 0) { - piCout << "[piConnectU] Error: can`t find suitable pair of event \"" << ename << "\" in class \"" << src->className() + piCout << "[piConnectU] Error: can`t find suitable pair of event \"" << sig << "\" in class \"" << src->className() << "\" and handler \"" << hname << "\" in class \"" << dest_o->className() << "\"! (" << loc << ")"; return false; } - src->connections << PIObject::__Connection(addr_dest, addr_src, ename, dest_o, dest, args, performer); + src->connections << PIObject::__Connection(addr_dest, addr_src, sig, dest_o, dest, args, performer); if (que) performer->proc_event_queue = true; dest_o->connectors << src; //piCout << cc << cq << _ol.size();//"connect" << src << "->" << dest_o << ", dest.connectors.size() =" << dest_o->connectors.size(); @@ -322,12 +322,48 @@ bool PIObject::piConnectU(PIObject * src, const PIString & ename, PIObject * des } +#ifdef PIP_CXX11_SUPPORT +bool PIObject::piConnectLS(PIObject * src, const PIString & sig, std::function * f, const char * loc) { + if (src == 0) { + delete f; + return false; + } + if (!src->isPIObject()) { + piCout << "[piConnectLS] \"" << sig << "\" -> [lambda] error: source object is not PIObject! (" << loc << ")"; + delete f; + return false; + } + PIMutexLocker ml(__meta_mutex()); + PIMutexLocker mls(src->mutex_connect); + //piCout << "locked"; + PIVector<__MetaFunc> m_src = src->findEH(sig); + if (m_src.isEmpty()) { + piCout << "[piConnectLS] Error: can`t find event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")"; + delete f; + return false; + } + if (m_src.size() != 1) { + piCout << "[piConnectLS] Error: can`t connect overloaded event \"" << sig << "\" in class \"" << src->className() << "\"! (" << loc << ")"; + delete f; + return false; + } + PIObject::__Connection conn(0, m_src[0].addr, sig); + //piCout << "found"; + conn.functor = f; + src->connections << conn; + //piCout << "finished"; + return true; +} +#endif + + void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * dest, void * ev_h) { PIMutexLocker _ml(src->mutex_connect); PIMutexLocker _mld(dest->mutex_connect, src != dest); for (int i = 0; i < src->connections.size_s(); ++i) { __Connection & cc(src->connections[i]); if (cc.event == sig && cc.dest_o == dest && cc.slot == ev_h) { + src->connections[i].destroy(); src->connections.remove(i); i--; } @@ -342,6 +378,7 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig, PIObject * des for (int i = 0; i < src->connections.size_s(); ++i) { __Connection & cc(src->connections[i]); if (cc.event == sig && cc.dest_o == dest) { + src->connections[i].destroy(); src->connections.remove(i); i--; } @@ -356,12 +393,15 @@ void PIObject::piDisconnect(PIObject * src, const PIString & sig) { __Connection & cc(src->connections[i]); if (cc.event == sig) { PIObject * dest = cc.dest_o; - src->connections.remove(i); - i--; + if (!dest) { + src->connections[i].destroy(); + src->connections.remove(i); + i--; #if !defined(ANDROID) && !defined(MAC_OS) && !defined(FREERTOS) - PIMutexLocker _mld(dest->mutex_connect, src != dest); + PIMutexLocker _mld(dest->mutex_connect, src != dest); #endif - dest->updateConnectors(); + dest->updateConnectors(); + } } } } @@ -380,17 +420,23 @@ void PIObject::piDisconnect(PIObject * src) { #endif PIVector<__Connection> & oc(o->connections); for (int i = 0; i < oc.size_s(); ++i) { + if (oc[i].functor) continue; //piCout << " check" << (void*)(oc[i].dest_o) << "==" << (void*)(src); if (oc[i].dest_o == src) { + oc[i].destroy(); oc.remove(i); --i; } } } piForeachC (PIObject::__Connection & c, src->connections) { + if (c.functor) continue; + if (!c.dest_o) continue; if (!c.dest_o->isPIObject()) continue; c.dest_o->connectors.remove(src); } + for (int i = 0; i < src->connections.size_s(); ++i) + src->connections[i].destroy(); src->connections.clear(); } @@ -562,14 +608,18 @@ void PIObject::dump(const PIString & line_prefix) const { //printf("dump %d connections\n",connections.size()); piForeachC (__Connection & c, connections) { PIObject * dst = c.dest_o; - __MetaFunc hf = dst->methodEH(c.slot); __MetaFunc ef = methodEH(c.signal); - if (hf.func_name.isEmpty()) hf.func_name = "[BROKEN]"; - else hf.func_name += "(" + hf.arguments() + ")"; PIString src(c.event); if (!ef.func_name.isEmpty()) src = ef.func_name + "(" + ef.arguments() + ")"; - PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf.func_name; + if (dst) { + __MetaFunc hf = dst->methodEH(c.slot); + if (hf.func_name.isEmpty()) hf.func_name = "[BROKEN]"; + else hf.func_name += "(" + hf.arguments() + ")"; + PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf.func_name; + } else { + PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << "[lambda]"; + } } //printf("dump %d connections ok\n",connections.size()); PICout(PICoutManipulators::AddNewLine) << line_prefix << " }"; @@ -630,3 +680,13 @@ void PIObject::__MetaData::addScope(const PIString & s) { scope_id << s.hash(); } } + + + + +void PIObject::__Connection::destroy() { +#ifdef PIP_CXX11_SUPPORT + if (functor) delete functor; + functor = nullptr; +#endif +} diff --git a/src_main/core/piobject.h b/src_main/core/piobject.h index 9a309a07..cfa77b5c 100755 --- a/src_main/core/piobject.h +++ b/src_main/core/piobject.h @@ -114,6 +114,9 @@ /// 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) @@ -452,6 +455,9 @@ #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); +#ifdef PIP_CXX11_SUPPORT +# define CONNECTL(src, event, functor) PIObject::piConnectLS(src, PIStringAscii(#event), PIObject::__newFunctor(&(src)->__stat_eh_##event##__, functor), LOCATION); +#endif #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); @@ -590,8 +596,15 @@ 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, PIObject * performer = 0); - + static bool piConnectU(PIObject * src, const PIString & sig, PIObject * dest_o, void * dest, const PIString & hname, const char * loc, PIObject * performer = 0); +#ifdef PIP_CXX11_SUPPORT + static bool piConnectLS(PIObject * src, const PIString & sig, std::function * f, const char * loc); + template + static std::function * __newFunctor(void(*stat_handler)(void*,TYPES...), INPUT functor) { + return (std::function*)(new std::function(functor)); + } +#endif + // / 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); @@ -612,15 +625,23 @@ public: for (int j = 0; j < sender->connections.size_s(); ++j) { __Connection & i(sender->connections[j]); if (i.eventID != eventID) continue; - if (i.performer) { - i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender)); +#ifdef PIP_CXX11_SUPPORT + if (i.functor) { + (*(i.functor))(); } 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(); +#endif + 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(); + } +#ifdef PIP_CXX11_SUPPORT } +#endif } } @@ -629,18 +650,26 @@ public: for (int j = 0; j < sender->connections.size_s(); ++j) { __Connection & i(sender->connections[j]); if (i.eventID != eventID) continue; - if (i.performer) { - PIVector vl; - if (i.args_count > 0) vl << PIVariant::fromValue(v0); - i.performer->postQueuedEvent(__QueuedEvent(i.slot, i.dest, i.dest_o, sender, vl)); +#ifdef PIP_CXX11_SUPPORT + if (i.functor) { + (*((std::function*)i.functor))(v0); } 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(); +#endif + if (i.performer) { + PIVector 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(); + } +#ifdef PIP_CXX11_SUPPORT } +#endif } } template @@ -648,22 +677,30 @@ public: for (int j = 0; j < sender->connections.size_s(); ++j) { __Connection & i(sender->connections[j]); if (i.eventID != eventID) continue; - if (i.performer) { - PIVector 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)); +#ifdef PIP_CXX11_SUPPORT + if (i.functor) { + (*((std::function*)i.functor))(v0, v1); } 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; +#endif + if (i.performer) { + PIVector 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(); +#ifdef PIP_CXX11_SUPPORT } +#endif } } template @@ -671,24 +708,32 @@ public: for (int j = 0; j < sender->connections.size_s(); ++j) { __Connection & i(sender->connections[j]); if (i.eventID != eventID) continue; - if (i.performer) { - PIVector 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)); +#ifdef PIP_CXX11_SUPPORT + if (i.functor) { + (*((std::function*)i.functor))(v0, v1, v2); } 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; +#endif + if (i.performer) { + PIVector 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(); +#ifdef PIP_CXX11_SUPPORT } +#endif } } template @@ -696,26 +741,34 @@ public: for (int j = 0; j < sender->connections.size_s(); ++j) { __Connection & i(sender->connections[j]); if (i.eventID != eventID) continue; - if (i.performer) { - PIVector 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)); +#ifdef PIP_CXX11_SUPPORT + if (i.functor) { + (*((std::function*)i.functor))(v0, v1, v2, v3); } 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; +#endif + if (i.performer) { + PIVector 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(); +#ifdef PIP_CXX11_SUPPORT } +#endif } } @@ -815,9 +868,16 @@ private: dest = d; args_count = ac; performer = p; +#ifdef PIP_CXX11_SUPPORT + functor = 0; +#endif } + void destroy(); void * slot; void * signal; +#ifdef PIP_CXX11_SUPPORT + std::function * functor; +#endif PIString event; uint eventID; PIObject * dest_o;