piobject metasystem memory and performance optimization

This commit is contained in:
2022-04-22 15:35:25 +03:00
parent db54d0b052
commit 6485d81025
6 changed files with 177 additions and 116 deletions

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0017 NEW) # need include() with .cmake cmake_policy(SET CMP0017 NEW) # need include() with .cmake
project(pip) project(pip)
set(pip_MAJOR 2) set(pip_MAJOR 2)
set(pip_MINOR 35) set(pip_MINOR 36)
set(pip_REVISION 0) set(pip_REVISION 0)
set(pip_SUFFIX ) set(pip_SUFFIX )
set(pip_COMPANY SHS) set(pip_COMPANY SHS)

View File

@@ -338,7 +338,7 @@ PICout PICout::operator <<(const PIFlags<PICoutManipulators::PICoutFormat> & v)
} }
PICout PICout::operator <<(const char * v) {if (!act_) return *this; if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;} PICout PICout::operator <<(const char * v) {if (!act_ || !v) return *this; if (v[0] == '\0') return *this; space(); quote(); PICOUTTOTARGET(v) quote(); return *this;}
PICout PICout::operator <<(const bool v) {if (!act_) return *this; space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;} PICout PICout::operator <<(const bool v) {if (!act_) return *this; space(); if (v) PICOUTTOTARGET("true") else PICOUTTOTARGET("false") return *this;}

View File

@@ -110,22 +110,80 @@
//! \} //! \}
PIObject::__MetaFunc::__MetaFunc() {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
types[i] = names[i] = nullptr;
types_id[i] = 0;
}
}
int PIObject::__MetaFunc::argumentsCount() const {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i)
if (!types[i])
return i;
return __PIOBJECT_MAX_ARGS__;
}
PIString PIObject::__MetaFunc::arguments() const { PIString PIObject::__MetaFunc::arguments() const {
return types.join(","); PIString ret;
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
if (!types[i]) break;
if (!ret.isEmpty()) ret += ',';
ret += PIStringAscii(types[i]);
}
return ret;
} }
PIString PIObject::__MetaFunc::fullFormat() const { PIString PIObject::__MetaFunc::fullFormat() const {
PIString ret = type_ret + " " + scope + "::" + func_name +"("; PIString ret = PIStringAscii(type_ret) + " " +
for (int i = 0; i < types.size_s(); ++i) { PIStringAscii(scope) + "::" +
PIStringAscii(func_name) +"(";
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
if (!types[i]) break;
if (i > 0) ret += ", "; if (i > 0) ret += ", ";
ret += types[i] + " " + names[i]; ret += PIStringAscii(types[i]) + " " + PIStringAscii(names[i]);
} }
ret += ")"; ret += ")";
return ret; return ret;
} }
void PIObject::__MetaFunc::__setFuncName(const char * n) {
func_name = n;
func_name_id = PIStringAscii(n).hash();
}
void PIObject::__MetaFunc::__addArgument(const char * t, const char * n) {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
if (types[i]) continue;
types[i] = t;
names[i] = n;
types_id[i] = PIObject::simplifyType(t, false).hash();
break;
}
//PICout(PICoutManipulators::DefaultControls | PICoutManipulators::AddQuotes)
// << "__addArgument" << t << n << PIObject::simplifyType(t) << types_id.back();
}
bool PIObject::__MetaFunc::canConnectTo(const __MetaFunc & dst, int & args_count) const {
for (int i = 0; i < __PIOBJECT_MAX_ARGS__; ++i) {
//piCout << "canConnectTo" << i << types[i] << dst.types[i];
args_count = i;
if (!dst.types[i]) break;
if (!types[i]) return false;
if (types_id[i] != dst.types_id[i])
return false;
}
return true;
}
PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), emitter_(0), thread_safe_(false), proc_event_queue(false) { PIObject::PIObject(const PIString & name): _signature_(__PIOBJECT_SIGNATURE__), emitter_(0), thread_safe_(false), proc_event_queue(false) {
in_event_cnt = 0; in_event_cnt = 0;
setName(name); setName(name);
@@ -196,8 +254,13 @@ bool PIObject::executeQueued(PIObject * performer, const PIString & method, cons
PIStringList PIObject::scopeList() const { PIStringList PIObject::scopeList() const {
PIStringList ret;
ret.reserve(2);
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
return __meta_data()[classNameID()].scope_list; const PIVector<const char *> & scope(__meta_data()[classNameID()].scope_list);
for (const char * c: scope)
ret = PIStringAscii(c);
return ret;
} }
@@ -212,10 +275,11 @@ PIStringList PIObject::methodsEH() const {
bool PIObject::isMethodEHContains(const PIString & name) const { bool PIObject::isMethodEHContains(const PIString & name) const {
uint search_id = name.hash();
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
const __MetaData & ehd(__meta_data()[classNameID()]); const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) {
if (eh.value().func_name == name) if (eh.value().func_name_id == search_id)
return true; return true;
} }
return false; return false;
@@ -223,10 +287,11 @@ bool PIObject::isMethodEHContains(const PIString & name) const {
PIString PIObject::methodEHArguments(const PIString & name) const { PIString PIObject::methodEHArguments(const PIString & name) const {
uint search_id = name.hash();
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
const __MetaData & ehd(__meta_data()[classNameID()]); const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) {
if (eh.value().func_name == name) if (eh.value().func_name_id == search_id)
return eh.value().arguments(); return eh.value().arguments();
} }
return PIString(); return PIString();
@@ -234,10 +299,11 @@ PIString PIObject::methodEHArguments(const PIString & name) const {
PIString PIObject::methodEHFullFormat(const PIString & name) const { PIString PIObject::methodEHFullFormat(const PIString & name) const {
uint search_id = name.hash();
PIMutexLocker ml(__meta_mutex()); PIMutexLocker ml(__meta_mutex());
const __MetaData & ehd(__meta_data()[classNameID()]); const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) {
if (eh.value().func_name == name) if (eh.value().func_name_id == search_id)
return eh.value().fullFormat(); return eh.value().fullFormat();
} }
return PIString(); return PIString();
@@ -250,10 +316,11 @@ PIString PIObject::methodEHFromAddr(const void * addr) const {
PIVector<PIObject::__MetaFunc> PIObject::findEH(const PIString & name) const { PIVector<PIObject::__MetaFunc> PIObject::findEH(const PIString & name) const {
uint search_id = name.hash();
PIVector<__MetaFunc> ret; PIVector<__MetaFunc> ret;
const __MetaData & ehd(__meta_data()[classNameID()]); const __MetaData & ehd(__meta_data()[classNameID()]);
for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) { for (auto eh = ehd.eh_func.constBegin(); eh != ehd.eh_func.constEnd(); eh++) {
if (eh.value().func_name == name) if (eh.value().func_name_id == search_id)
ret << eh.value(); ret << eh.value();
} }
return ret; return ret;
@@ -313,10 +380,9 @@ PIObject::Connection PIObject::piConnectU(PIObject * src, const PIString & sig,
if (addr_src != 0) break; if (addr_src != 0) break;
piForeachC (__MetaFunc & fd, m_dest) { piForeachC (__MetaFunc & fd, m_dest) {
if (addr_src != 0) break; if (addr_src != 0) break;
if (fs.arguments().startsWith(fd.arguments()) || fd.arguments().isEmpty()) { if (fs.canConnectTo(fd, args)) {
addr_src = fs.addr; addr_src = fs.addr;
addr_dest = que ? fd.addrV : fd.addr; addr_dest = que ? fd.addrV : fd.addr;
args = fd.names.size_s();
} }
} }
} }
@@ -528,7 +594,7 @@ bool PIObject::findSuitableMethodV(const PIString & method, int args, int & ret_
int mfi = -1, ac = -1, mac = -1; int mfi = -1, ac = -1, mac = -1;
for (int i = 0; i < ml.size_s(); ++i) { for (int i = 0; i < ml.size_s(); ++i) {
__MetaFunc & m(ml[i]); __MetaFunc & m(ml[i]);
int j = m.names.size_s(); int j = m.argumentsCount();
if (mac < 0 || mac > j) mac = j; if (mac < 0 || mac > j) mac = j;
if ((j <= args) && (ac < j)) { if ((j <= args) && (ac < j)) {
ac = j; ac = j;
@@ -570,8 +636,9 @@ void PIObject::callAddrV(void * slot, void * obj, int args, const PIVector<PIVar
} }
PIString PIObject::simplifyType(const char * a) { PIString PIObject::simplifyType(const char * a, bool readable) {
PIString ret = PIStringAscii(a).trim(); PIString ret = PIStringAscii(a).trim();
if (readable) {
int white = -1; int white = -1;
for (int i = 0; i < ret.size_s(); ++i) { for (int i = 0; i < ret.size_s(); ++i) {
bool iw = ret[i] == ' ' || ret[i] == '\t' || ret[i] == '\r' || ret[i] == '\n'; bool iw = ret[i] == ' ' || ret[i] == '\t' || ret[i] == '\r' || ret[i] == '\n';
@@ -590,10 +657,25 @@ PIString PIObject::simplifyType(const char * a) {
} }
} }
} }
ret.replaceAll(" &", "&"); ret.replaceAll(" [", '[');
ret.replaceAll(" *", "*"); ret.replaceAll(" ]", ']');
ret.replaceAll(" <", '<');
ret.replaceAll(" >", '>');
ret.replaceAll(" &", '&');
ret.replaceAll(" *", '*');
ret.replaceAll("[ ", '[');
ret.replaceAll("] ", ']');
ret.replaceAll("< ", '<');
ret.replaceAll("> ", '>');
ret.replaceAll("& ", '&');
ret.replaceAll("* ", '*');
if (ret.startsWith("const ") && ret.endsWith("&")) if (ret.startsWith("const ") && ret.endsWith("&"))
ret.cutLeft(6).cutRight(1).trim(); ret.cutLeft(6).cutRight(1).trim();
} else {
if (ret.startsWith("const ") && ret.endsWith("&"))
ret.cutLeft(6).cutRight(1).trim();
ret.removeAll(' ').removeAll('\t').removeAll('\r').removeAll('\n');
}
return ret; return ret;
} }
@@ -632,13 +714,14 @@ void PIObject::dump(const PIString & line_prefix) const {
PIObject * dst = c.dest_o; PIObject * dst = c.dest_o;
__MetaFunc ef = methodEH(c.signal); __MetaFunc ef = methodEH(c.signal);
PIString src(c.event); PIString src(c.event);
if (!ef.func_name.isEmpty()) if (ef.func_name)
src = ef.func_name + "(" + ef.arguments() + ")"; src = PIStringAscii(ef.func_name) + "(" + ef.arguments() + ")";
if (dst) { if (dst) {
__MetaFunc hf = dst->methodEH(c.slot); __MetaFunc hf = dst->methodEH(c.slot);
if (hf.func_name.isEmpty()) hf.func_name = "[BROKEN]"; PIString hf_fn;
else hf.func_name += "(" + hf.arguments() + ")"; if (!hf.func_name) hf_fn = "[BROKEN]";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf.func_name; else hf_fn = PIStringAscii(hf.func_name) + "(" + hf.arguments() + ")";
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << dst->className() << " (" << c.dest << ", \"" << dst->name() << "\")::" << hf_fn;
} else { } else {
PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << "[lambda]"; PICout(PICoutManipulators::AddNewLine) << line_prefix << " " << src << " -> " << "[lambda]";
} }
@@ -693,7 +776,7 @@ bool dumpApplicationToFile(const PIString & path) {
#endif #endif
void PIObject::__MetaData::addScope(const PIString & s, uint shash) { void PIObject::__MetaData::addScope(const char * s, uint shash) {
if (!scope_id.contains(shash)) { if (!scope_id.contains(shash)) {
scope_list << s; scope_list << s;
scope_id << shash; scope_id << shash;

View File

@@ -34,7 +34,6 @@
#include "piqueue.h" #include "piqueue.h"
#include "piobject_macros.h" #include "piobject_macros.h"
typedef void (*Handler)(void * ); typedef void (*Handler)(void * );
class PIP_EXPORT PIObject { class PIP_EXPORT PIObject {
@@ -123,6 +122,7 @@ public:
virtual uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;} virtual uint classNameID() const {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
static const PIString __classNameS() {return PIStringAscii("PIObject");} static const PIString __classNameS() {return PIStringAscii("PIObject");}
static const char * __classNameCC() {return "PIObject";}
static uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;} static uint __classNameIDS() {static uint ret = PIStringAscii("PIObject").hash(); return ret;}
//! \~english Returns parent class name //! \~english Returns parent class name
@@ -437,7 +437,8 @@ public:
template<typename T> template<typename T>
bool isTypeOf() const { bool isTypeOf() const {
if (!isPIObject()) return false; if (!isPIObject()) return false;
return scopeList().contains(T::__classNameS()); PIMutexLocker ml(__meta_mutex());
return __meta_data()[classNameID()].scope_id.contains(T::__classNameIDS());
} }
//! \~english Returns cast to T if this is valid subclass "T" (check by \a isTypeOf()) or "nullptr" //! \~english Returns cast to T if this is valid subclass "T" (check by \a isTypeOf()) or "nullptr"
@@ -459,26 +460,32 @@ public:
static bool isTypeOf(const PIObject * o) {return o->isTypeOf<T>();} static bool isTypeOf(const PIObject * o) {return o->isTypeOf<T>();}
template<typename T> template<typename T>
static bool isTypeOf(const void * o) {return isTypeOf<T>((PIObject*)o);} static bool isTypeOf(const void * o) {return isTypeOf<T>((PIObject*)o);}
static PIString simplifyType(const char * a); static PIString simplifyType(const char * a, bool readable = true);
struct PIP_EXPORT __MetaFunc { struct PIP_EXPORT __MetaFunc {
__MetaFunc(): addr(0), addrV(0) {;} __MetaFunc();
bool isNull() const {return addr == 0;} bool isNull() const {return addr == nullptr;}
int argumentsCount() const;
PIString arguments() const; PIString arguments() const;
PIString fullFormat() const; PIString fullFormat() const;
void * addr; void __setFuncName(const char * n);
void * addrV; void __addArgument(const char * t, const char * n);
PIString func_name; bool canConnectTo(const __MetaFunc & dst, int & args_count) const;
PIString type_ret; void * addr = nullptr;
PIString scope; void * addrV = nullptr;
PIStringList types; uint func_name_id = 0;
PIStringList names; const char * func_name = nullptr;
const char * type_ret = nullptr;
const char * scope = nullptr;
const char * types[__PIOBJECT_MAX_ARGS__];
const char * names[__PIOBJECT_MAX_ARGS__];
uint types_id[__PIOBJECT_MAX_ARGS__];
}; };
struct PIP_EXPORT __MetaData { struct PIP_EXPORT __MetaData {
__MetaData() {scope_list << PIStringAscii("PIObject"); scope_id << PIStringAscii("PIObject").hash();} __MetaData() {scope_list << "PIObject"; scope_id << PIStringAscii("PIObject").hash();}
void addScope(const PIString & s, uint shash); void addScope(const char * s, uint shash);
PIStringList scope_list; PIVector<const char *> scope_list;
PISet<uint> scope_id; PISet<uint> scope_id;
PISet<const void * > eh_set; PISet<const void * > eh_set;
PIMap<const void * , __MetaFunc> eh_func; PIMap<const void * , __MetaFunc> eh_func;

View File

@@ -385,6 +385,7 @@
# define __PTYPE(t) __PIVariantTypeInfo__<t>::PureType # define __PTYPE(t) __PIVariantTypeInfo__<t>::PureType
#endif #endif
#define __VVALUE(t, v) v.value< __PTYPE(t) >() #define __VVALUE(t, v) v.value< __PTYPE(t) >()
#define __PIOBJECT_MAX_ARGS__ 4
#define PIOBJECT(name) \ #define PIOBJECT(name) \
@@ -392,6 +393,7 @@
typedef name __PIObject__; \ typedef name __PIObject__; \
public: \ public: \
static const PIString __classNameS() {static PIString ret = PIStringAscii(#name); return ret;} \ static const PIString __classNameS() {static PIString ret = PIStringAscii(#name); return ret;} \
static const char * __classNameCC() {return #name;} \
static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \ static uint __classNameIDS() {static uint ret = PIStringAscii(#name).hash(); return ret;} \
virtual const char * className() const {return #name;} \ virtual const char * className() const {return #name;} \
virtual uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \ virtual uint classNameID() const {static uint ret = PIStringAscii(#name).hash(); return ret;} \
@@ -411,7 +413,7 @@
__MetaData & eh(__meta_data()[id]); \ __MetaData & eh(__meta_data()[id]); \
eh.eh_set << ehp.eh_set; \ eh.eh_set << ehp.eh_set; \
eh.eh_func << ehp.eh_func; \ eh.eh_func << ehp.eh_func; \
eh.addScope(__classNameS(), id); \ eh.addScope(__classNameCC(), id); \
} \ } \
}; \ }; \
__BaseInitializer__ __base_init__; __BaseInitializer__ __base_init__;
@@ -431,7 +433,7 @@
eh.eh_func << ehp.eh_func; \ eh.eh_func << ehp.eh_func; \
eh.scope_id = ehp.scope_id; \ eh.scope_id = ehp.scope_id; \
eh.scope_list = ehp.scope_list; \ eh.scope_list = ehp.scope_list; \
eh.addScope(__classNameS(), id); \ eh.addScope(__classNameCC(), id); \
} \ } \
}; \ }; \
__ParentInitializer__ __parent_init__; \ __ParentInitializer__ __parent_init__; \
@@ -443,92 +445,61 @@
#define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent) #define PIOBJECT_SUBCLASS(name, parent) PIOBJECT(name) PIOBJECT_PARENT(parent)
#define EH_INIT0(ret, name) \ #define __EH_INIT_BASE__(ret, name) \
STATIC_INITIALIZER_BEGIN \
PIMutexLocker ml(__meta_mutex()); \ PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \ __MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \
void * fpV = fp; \
if (eh.eh_set[fp]) return; \ if (eh.eh_set[fp]) return; \
eh.eh_set << fp; \ eh.eh_set << fp; \
__MetaFunc & f(eh.eh_func[fp]); \ __MetaFunc & f(eh.eh_func[fp]); \
f.scope = __classNameS(); \ f.scope = __classNameCC(); \
f.func_name = PIStringAscii(#name); \ f.__setFuncName(#name); \
f.addr = fp; \ f.addr = fp; \
f.addrV = fpV; \ f.addrV = fpV; \
f.type_ret = PIStringAscii(#ret); \ f.type_ret = #ret;
#define EH_INIT0(ret, name) \
STATIC_INITIALIZER_BEGIN \
void * fp = (void*)(ret(*)(void*))__stat_eh_##name##__; \
void * fpV = fp; \
__EH_INIT_BASE__(ret, name) \
STATIC_INITIALIZER_END STATIC_INITIALIZER_END
#define EH_INIT1(ret, name, a0, n0) \ #define EH_INIT1(ret, name, a0, n0) \
STATIC_INITIALIZER_BEGIN \ STATIC_INITIALIZER_BEGIN \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \ void * fp = (void*)(ret(*)(void*, a0))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &))__stat_eh_v_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \ __EH_INIT_BASE__(ret, name) \
eh.eh_set << fp; \ f.__addArgument(#a0, #n0); \
__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 STATIC_INITIALIZER_END
#define EH_INIT2(ret, name, a0, n0, a1, n1) \ #define EH_INIT2(ret, name, a0, n0, a1, n1) \
STATIC_INITIALIZER_BEGIN \ STATIC_INITIALIZER_BEGIN \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \ void * fp = (void*)(ret(*)(void*, a0, a1))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \ __EH_INIT_BASE__(ret, name) \
eh.eh_set << fp; \ f.__addArgument(#a0, #n0); \
__MetaFunc & f(eh.eh_func[fp]); \ f.__addArgument(#a1, #n1); \
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 STATIC_INITIALIZER_END
#define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \ #define EH_INIT3(ret, name, a0, n0, a1, n1, a2, n2) \
STATIC_INITIALIZER_BEGIN \ STATIC_INITIALIZER_BEGIN \
PIMutexLocker ml(__meta_mutex()); \
__MetaData & eh(__meta_data()[__classNameIDS()]); \
void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \ void * fp = (void*)(ret(*)(void*, a0, a1, a2))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \ __EH_INIT_BASE__(ret, name) \
eh.eh_set << fp; \ f.__addArgument(#a0, #n0); \
__MetaFunc & f(eh.eh_func[fp]); \ f.__addArgument(#a1, #n1); \
f.scope = __classNameS(); \ f.__addArgument(#a2, #n2); \
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 STATIC_INITIALIZER_END
#define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \ #define EH_INIT4(ret, name, a0, n0, a1, n1, a2, n2, a3, n3) \
STATIC_INITIALIZER_BEGIN \ 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 * fp = (void*)(ret(*)(void*, a0, a1, a2, a3))__stat_eh_##name##__; \
void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \ void * fpV = (void*)(ret(*)(void*, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &, const PIVariantSimple &))__stat_eh_v_##name##__; \
if (eh.eh_set[fp]) return; \ __EH_INIT_BASE__(ret, name) \
eh.eh_set << fp; \ f.__addArgument(#a0, #n0); \
__MetaFunc & f(eh.eh_func[fp]); \ f.__addArgument(#a1, #n1); \
f.scope = __classNameS(); \ f.__addArgument(#a2, #n2); \
f.func_name = PIStringAscii(#name); \ f.__addArgument(#a3, #n3); \
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 STATIC_INITIALIZER_END

View File

@@ -376,7 +376,7 @@ TEST(PIMathMatrixT_Test, invert) {
d2 = matrix2.determinant(); d2 = matrix2.determinant();
matrix3 = matrix1; matrix3 = matrix1;
matrix1.invert(); matrix1.invert();
ASSERT_TRUE((matrix1 == matrix3) && (d1 == 1/d2)); ASSERT_TRUE((matrix1 == matrix3) && piCompare(d1, 1/d2));
} }
TEST(PIMathMatrixT_Test, inverted) { TEST(PIMathMatrixT_Test, inverted) {