diff --git a/CMakeLists.txt b/CMakeLists.txt index 811c3b14..a0b51dbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ option(ICU "Unicode support" 1) option(USB "USB support" 0) option(STL "Building with STL containers" 0) option(CRYPT "Crypt support" 0) +option(INTROSPECTION "Build with introspection" 1) option(LIB "System install" 1) option(DEBUG "Build with -g3" 0) set(CMAKE_BUILD_TYPE "Release") @@ -140,6 +141,16 @@ else () endif () +# Check if PIP should be built with introspection +if (INTROSPECTION) + message(STATUS "Building with introspection") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPIP_INTROSPECTION") + list(APPEND LIBS sodium) +else () + message(STATUS "Building without introspection") +endif () + + # Add library if (${APPLE}) add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) diff --git a/main.cpp b/main.cpp index e29b2635..0869f0d6 100644 --- a/main.cpp +++ b/main.cpp @@ -8,7 +8,9 @@ int main (int argc, char * argv[]) { - piCout << PIINTROSPECTION; + //PIByteArray ba; + PIString str; + piCout << PIINTROSPECTION_CONTAINERS->count; /*PIVector vl; vl << PIVariant('2') << PIVariant(-5.5) << PIVariant(10) << PIVariant(complexd(2,3)) << PIVariant("text") << PIVariant(PIByteArray("bytearray", 9)) << PIVariant(PIDateTime::current()); piForeachC (PIVariant v, vl) diff --git a/src/containers/pideque.h b/src/containers/pideque.h index 6ec1b102..6008415f 100755 --- a/src/containers/pideque.h +++ b/src/containers/pideque.h @@ -26,6 +26,7 @@ #define PIDEQUE_H #include "piincludes.h" +#include "piintrospection_proxy.h" #if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN) @@ -35,27 +36,33 @@ template class PIDeque { public: PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + PIINTROSPECTION_CONTAINER_NEW() //printf("new vector 1 %p (%s) ... !{\n", this, typeid(T).name()); //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); } PIDeque(const PIDeque & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + PIINTROSPECTION_CONTAINER_NEW() //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); alloc(other.pid_size, true); newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); } PIDeque(const T * data, size_t size): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + PIINTROSPECTION_CONTAINER_NEW() //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name()); alloc(size, true); newT(pid_data + pid_start, data, pid_size); //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); } PIDeque(size_t pid_size, const T & f = T()): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { + PIINTROSPECTION_CONTAINER_NEW() //printf("new vector 3 %p (%s) ... !{\n", this, typeid(T).name()); resize(pid_size, f); //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); } ~PIDeque() { + PIINTROSPECTION_CONTAINER_DELETE() + PIINTROSPECTION_CONTAINER_FREE((pid_rsize)*sizeof(T)) //printf("delete deque %p (%s) (s=%d, rs=%d, st=%d, d=%p) ... ~{\n", this, typeid(T).name(), int(pid_size), int(pid_rsize), int(pid_start), pid_data); deleteT(pid_data + pid_start, pid_size); dealloc(); @@ -197,6 +204,7 @@ public: alloc(new_size, true); //if (sizeof(T) == 1) memset(&(pid_data[os]), f, ds); //zeroRaw(&(pid_data[os]), new_size - os); + PIINTROSPECTION_CONTAINER_USED((new_size-os)*sizeof(T)) for (size_t i = os + pid_start; i < new_size + pid_start; ++i) elementNew(pid_data + i, f); } return *this; @@ -225,6 +233,7 @@ public: memmove(&(pid_data[pid_start]), &(pid_data[pid_start + 1]), index * sizeof(T)); } //piCout << "insert" << pid_start << index << (pid_start + ssize_t(index)) << pid_size << ">!"; + PIINTROSPECTION_CONTAINER_USED(sizeof(T)) elementNew(pid_data + pid_start + index, v); return *this; } @@ -330,6 +339,7 @@ private: return (1 << t); } inline void newT(T * dst, const T * src, size_t s) { + PIINTROSPECTION_CONTAINER_USED(s*sizeof(T)) for (size_t i = 0; i < s; ++i) elementNew(dst + i, src[i]); } @@ -346,6 +356,7 @@ private: else pid_tdata = (T*)(realloc(pid_tdata, s * sizeof(T))); }*/ inline void deleteT(T * d, size_t sz) { + PIINTROSPECTION_CONTAINER_UNUSED(sz*sizeof(T)) //std::cout << " ~[("< %d (%p)\n", this, pid_rsize, as, pid_data); + PIINTROSPECTION_CONTAINER_ALLOC((as-pid_rsize)*sizeof(T)) pid_data = (T*)(realloc(pid_data, as*sizeof(T))); pid_rsize = as; //printf("(%p) realloc done (%p)\n", this, pid_data); @@ -425,6 +437,7 @@ private: T * td = newRaw(as); ssize_t ns = pid_start + as - pid_rsize; //printf("%X pid_start ost=%d ors=%d nst=%d nrs=%d\n", this, pid_start, pid_rsize, ns, as); + PIINTROSPECTION_CONTAINER_ALLOC((as-pid_rsize)*sizeof(T)) if (pid_rsize > 0 && pid_data != 0) { //printf("%X copy from %p + %d to %p + %d %d el\n", this, pid_data, pid_start, td, ns, pid_size); memcpy(td + ns, pid_data + pid_start, pid_size * sizeof(T)); diff --git a/src/system/piintrospection.cpp b/src/system/piintrospection.cpp new file mode 100644 index 00000000..fa7dd49c --- /dev/null +++ b/src/system/piintrospection.cpp @@ -0,0 +1,94 @@ +/* + PIP - Platform Independent Primitives + Introspection module + Copyright (C) 2016 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piintrospection.h" + + +PIIntrospectionContainers::PIIntrospectionContainers() { + count = 0; + bytes_allocated = bytes_used = 0; +} + + +PIIntrospectionThreads::PIIntrospectionThreads() { +} + + +PIIntrospectionContainers * __PIIntrospectionContainers__::p = 0; +PIIntrospectionThreads * __PIIntrospectionThreads__::p = 0; + + +void PIIntrospectionThreads::registerThread(int id, short prior, const PIString & name) { + mutex.lock(); + ThreadInfo & ti(threads[id]); + ti.id = id; + ti.priority = prior; + ti.name = name; + //piCout << "register thread" << id << name; + mutex.unlock(); +} + + +void PIIntrospectionThreads::unregisterThread(int id) { + mutex.lock(); + threads.remove(id); + mutex.unlock(); +} + + +void PIIntrospectionContainers::containerNew() { + mutex.lock(); + count++; + mutex.unlock(); +} + + +void PIIntrospectionContainers::containerDelete() { + mutex.lock(); + count--; + mutex.unlock(); +} + + +void PIIntrospectionContainers::containerAlloc(ullong cnt) { + mutex.lock(); + bytes_allocated += cnt; + mutex.unlock(); +} + + +void PIIntrospectionContainers::containerFree(ullong cnt) { + mutex.lock(); + bytes_allocated -= cnt; + mutex.unlock(); +} + + +void PIIntrospectionContainers::containerUsed(ullong cnt) { + mutex.lock(); + bytes_used += cnt; + mutex.unlock(); +} + + +void PIIntrospectionContainers::containerUnused(ullong cnt) { + mutex.lock(); + bytes_used -= cnt; + mutex.unlock(); +} diff --git a/src/system/piintrospection.h b/src/system/piintrospection.h new file mode 100644 index 00000000..31f32a12 --- /dev/null +++ b/src/system/piintrospection.h @@ -0,0 +1,90 @@ +/* + PIP - Platform Independent Primitives + Introspection module + Copyright (C) 2016 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIINTROSPECTION_H +#define PIINTROSPECTION_H + +#include "pistring.h" +#include "pimutex.h" + + +class PIP_EXPORT PIIntrospectionThreads +{ + friend class __PIIntrospectionThreads__; + PIIntrospectionThreads(); +public: + struct ThreadInfo { + ThreadInfo() {id = 0; priority = 0;} + PIString name; + int id; + short priority; + }; + + void registerThread(int id, short prior, const PIString & name); + void unregisterThread(int id); + + PIMap threads; + PIMutex mutex; +}; + + +class PIP_EXPORT PIIntrospectionContainers +{ + friend class __PIIntrospectionContainers__; + PIIntrospectionContainers(); +public: + void containerNew(); + void containerDelete(); + void containerAlloc(ullong cnt); + void containerFree(ullong cnt); + void containerUsed(ullong cnt); + void containerUnused(ullong cnt); + + uint count; + ullong bytes_allocated; + ullong bytes_used; + PIMutex mutex; +}; + + +class __PIIntrospectionContainers__ { +public: + __PIIntrospectionContainers__() {if (!p) p = new PIIntrospectionContainers();} + static PIIntrospectionContainers * get() {static __PIIntrospectionContainers__ * r = new __PIIntrospectionContainers__(); return r->p;} + static PIIntrospectionContainers * p; +}; + + +class __PIIntrospectionThreads__ { +public: + __PIIntrospectionThreads__() {if (!p) p = new PIIntrospectionThreads();} + static PIIntrospectionThreads * get() {static __PIIntrospectionThreads__ * r = new __PIIntrospectionThreads__(); return r->p;} + static PIIntrospectionThreads * p; +}; + +inline PIByteArray & operator <<(PIByteArray & b, const PIIntrospectionContainers & v) {b << v.count << v.bytes_allocated << v.bytes_used; return b;} +inline PIByteArray & operator <<(PIByteArray & b, const PIIntrospectionThreads::ThreadInfo & v) {b << v.id << v.priority << v.name; return b;} + +inline PIByteArray & operator >>(PIByteArray & b, PIIntrospectionContainers & v) {b >> v.count >> v.bytes_allocated >> v.bytes_used; return b;} +inline PIByteArray & operator >>(PIByteArray & b, PIIntrospectionThreads::ThreadInfo & v) {b >> v.id >> v.priority >> v.name; return b;} + +#define PIINTROSPECTION_CONTAINERS __PIIntrospectionContainers__::get() +#define PIINTROSPECTION_THREADS __PIIntrospectionThreads__::get() + +#endif // PIINTROSPECTION_H diff --git a/src/system/piintrospection_proxy.cpp b/src/system/piintrospection_proxy.cpp new file mode 100644 index 00000000..163a90a3 --- /dev/null +++ b/src/system/piintrospection_proxy.cpp @@ -0,0 +1,30 @@ +/* + PIP - Platform Independent Primitives + Introspection module + Copyright (C) 2016 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "piintrospection_proxy.h" +#include "piintrospection.h" + +void __PIIntrospection__registerThread(int id, short prior, const PIString & name) {PIINTROSPECTION_THREADS->registerThread(id, prior, name);} +void __PIIntrospection__unregisterThread(int id) {PIINTROSPECTION_THREADS->unregisterThread(id);} +void __PIIntrospection__containerNew() {PIINTROSPECTION_CONTAINERS->containerNew();} +void __PIIntrospection__containerDelete() {PIINTROSPECTION_CONTAINERS->containerDelete();} +void __PIIntrospection__containerAlloc(ullong cnt) {PIINTROSPECTION_CONTAINERS->containerAlloc(cnt);} +void __PIIntrospection__containerFree(ullong cnt) {PIINTROSPECTION_CONTAINERS->containerFree(cnt);} +void __PIIntrospection__containerUsed(ullong cnt) {PIINTROSPECTION_CONTAINERS->containerUsed(cnt);} +void __PIIntrospection__containerUnused(ullong cnt) {PIINTROSPECTION_CONTAINERS->containerUnused(cnt);} diff --git a/src/system/piintrospection_proxy.h b/src/system/piintrospection_proxy.h new file mode 100644 index 00000000..fca81f4c --- /dev/null +++ b/src/system/piintrospection_proxy.h @@ -0,0 +1,56 @@ +/* + PIP - Platform Independent Primitives + Introspection module + Copyright (C) 2016 Ivan Pelipenko peri4ko@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PIINTROSPECTION_PROXY_H +#define PIINTROSPECTION_PROXY_H + +#include "pibase.h" + +class PIString; + +void __PIIntrospection__registerThread(int id, short prior, const PIString & name); +void __PIIntrospection__unregisterThread(int id); +void __PIIntrospection__containerNew(); +void __PIIntrospection__containerDelete(); +void __PIIntrospection__containerAlloc(ullong cnt); +void __PIIntrospection__containerFree(ullong cnt); +void __PIIntrospection__containerUsed(ullong cnt); +void __PIIntrospection__containerUnused(ullong cnt); + +#ifdef PIP_INTROSPECTION +# define PIINTROSPECTION_CONTAINER_NEW() __PIIntrospection__containerNew(); +# define PIINTROSPECTION_CONTAINER_DELETE() __PIIntrospection__containerDelete(); +# define PIINTROSPECTION_CONTAINER_USED(cnt) __PIIntrospection__containerUsed(cnt); +# define PIINTROSPECTION_CONTAINER_UNUSED(cnt) __PIIntrospection__containerUnused(cnt); +# define PIINTROSPECTION_CONTAINER_ALLOC(cnt) __PIIntrospection__containerAlloc(cnt); +# define PIINTROSPECTION_CONTAINER_FREE(cnt) __PIIntrospection__containerFree(cnt); +# define PIINTROSPECTION_REGISTER_THREAD(id, pr, name) __PIIntrospection__registerThread(id, pr, name); +# define PIINTROSPECTION_UNREGISTER_THREAD(id) __PIIntrospection__unregisterThread(id); +#else +# define PIINTROSPECTION_CONTAINER_NEW() +# define PIINTROSPECTION_CONTAINER_DELETE() +# define PIINTROSPECTION_CONTAINER_USED(tcnt) +# define PIINTROSPECTION_CONTAINER_UNUSED(cnt) +# define PIINTROSPECTION_CONTAINER_ALLOC(cnt) +# define PIINTROSPECTION_CONTAINER_FREE(cnt) +# define PIINTROSPECTION_REGISTER_THREAD(id, pr, name) +# define PIINTROSPECTION_UNREGISTER_THREAD(id) +#endif + +#endif // PIINTROSPECTION_PROXY_H diff --git a/src/thread/pithread.cpp b/src/thread/pithread.cpp index 12671c56..eeb5d509 100755 --- a/src/thread/pithread.cpp +++ b/src/thread/pithread.cpp @@ -19,7 +19,7 @@ #include "pithread.h" #include "pisystemtests.h" -#include "piintrospection.h" +#include "piintrospection_proxy.h" #include #ifdef WINDOWS void __PISetTimerResolution() {if (setTimerResolutionAddr == NULL) return; ULONG ret; setTimerResolutionAddr(1, TRUE, &ret);} @@ -187,7 +187,7 @@ bool PIThread::startOnce() { void PIThread::terminate() { if (thread == 0) return; - PIINTROSPECTION->unregisterThread(tid()); + PIINTROSPECTION_UNREGISTER_THREAD(tid()); terminating = running_ = false; tid_ = -1; //piCout << "terminate" << thread; @@ -219,7 +219,7 @@ __THREAD_FUNC__ PIThread::thread_function(void * t) { __PISetTimerResolution(); #endif PIThread & ct = *((PIThread * )t); - PIINTROSPECTION->registerThread(ct.tid(), ct.priority(), ct.name()); + PIINTROSPECTION_REGISTER_THREAD(ct.tid(), ct.priority(), ct.name()); ct.running_ = true; if (ct.lockRun) ct.mutex_.lock(); ct.begin(); @@ -251,7 +251,7 @@ __THREAD_FUNC__ PIThread::thread_function(void * t) { ct.tid_ = -1; //cout << "thread " << t << " exiting ... " << endl; //piCout << "pthread_exit" << ct.thread; - PIINTROSPECTION->unregisterThread(ct.tid()); + PIINTROSPECTION_UNREGISTER_THREAD(ct.tid()); #ifndef WINDOWS pthread_detach(ct.thread); ct.thread = 0; @@ -276,7 +276,7 @@ __THREAD_FUNC__ PIThread::thread_function_once(void * t) { __PISetTimerResolution(); #endif PIThread & ct = *((PIThread * )t); - PIINTROSPECTION->registerThread(ct.tid(), ct.priority(), ct.name()); + PIINTROSPECTION_REGISTER_THREAD(ct.tid(), ct.priority(), ct.name()); ct.running_ = true; ct.begin(); ct.started(); @@ -290,7 +290,7 @@ __THREAD_FUNC__ PIThread::thread_function_once(void * t) { ct.tid_ = -1; //cout << "thread " << t << " exiting ... " << endl; //piCout << "pthread_exit" << ct.thread; - PIINTROSPECTION->unregisterThread(ct.tid()); + PIINTROSPECTION_UNREGISTER_THREAD(ct.tid()); #ifndef WINDOWS pthread_detach(ct.thread); ct.thread = 0;