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

This commit is contained in:
2016-03-01 16:16:23 +00:00
parent 2b7bf4a65e
commit 0d77d3b425
8 changed files with 303 additions and 7 deletions

View File

@@ -35,6 +35,7 @@ option(ICU "Unicode support" 1)
option(USB "USB support" 0) option(USB "USB support" 0)
option(STL "Building with STL containers" 0) option(STL "Building with STL containers" 0)
option(CRYPT "Crypt support" 0) option(CRYPT "Crypt support" 0)
option(INTROSPECTION "Build with introspection" 1)
option(LIB "System install" 1) option(LIB "System install" 1)
option(DEBUG "Build with -g3" 0) option(DEBUG "Build with -g3" 0)
set(CMAKE_BUILD_TYPE "Release") set(CMAKE_BUILD_TYPE "Release")
@@ -140,6 +141,16 @@ else ()
endif () 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 # Add library
if (${APPLE}) if (${APPLE})
add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE)

View File

@@ -8,7 +8,9 @@
int main (int argc, char * argv[]) { int main (int argc, char * argv[]) {
piCout << PIINTROSPECTION; //PIByteArray ba;
PIString str;
piCout << PIINTROSPECTION_CONTAINERS->count;
/*PIVector<PIVariant> vl; /*PIVector<PIVariant> vl;
vl << PIVariant('2') << PIVariant(-5.5) << PIVariant(10) << PIVariant(complexd(2,3)) << PIVariant("text") << PIVariant(PIByteArray("bytearray", 9)) << PIVariant(PIDateTime::current()); 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) piForeachC (PIVariant v, vl)

View File

@@ -26,6 +26,7 @@
#define PIDEQUE_H #define PIDEQUE_H
#include "piincludes.h" #include "piincludes.h"
#include "piintrospection_proxy.h"
#if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN) #if !defined(PIP_CONTAINERS_STL) || defined(DOXYGEN)
@@ -35,27 +36,33 @@ template <typename T>
class PIDeque { class PIDeque {
public: public:
PIDeque(): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { 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("new vector 1 %p (%s) ... !{\n", this, typeid(T).name());
//printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data);
} }
PIDeque(const PIDeque<T> & other): pid_data(0), pid_size(0), pid_rsize(0), pid_start(0) { PIDeque(const PIDeque<T> & 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()); //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name());
alloc(other.pid_size, true); alloc(other.pid_size, true);
newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size); newT(pid_data + pid_start, other.pid_data + other.pid_start, pid_size);
//printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); //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) { 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()); //printf("new vector 2 %p (%s) ... !{\n", this, typeid(T).name());
alloc(size, true); alloc(size, true);
newT(pid_data + pid_start, data, pid_size); newT(pid_data + pid_start, data, pid_size);
//printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); //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) { 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()); //printf("new vector 3 %p (%s) ... !{\n", this, typeid(T).name());
resize(pid_size, f); resize(pid_size, f);
//printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data); //printf("(s=%d, d=%p) }!\n", int(pid_size), pid_data);
} }
~PIDeque() { ~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); //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); deleteT(pid_data + pid_start, pid_size);
dealloc(); dealloc();
@@ -197,6 +204,7 @@ public:
alloc(new_size, true); alloc(new_size, true);
//if (sizeof(T) == 1) memset(&(pid_data[os]), f, ds); //if (sizeof(T) == 1) memset(&(pid_data[os]), f, ds);
//zeroRaw(&(pid_data[os]), new_size - os); //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); for (size_t i = os + pid_start; i < new_size + pid_start; ++i) elementNew(pid_data + i, f);
} }
return *this; return *this;
@@ -225,6 +233,7 @@ public:
memmove(&(pid_data[pid_start]), &(pid_data[pid_start + 1]), index * sizeof(T)); 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 << ">!"; //piCout << "insert" << pid_start << index << (pid_start + ssize_t(index)) << pid_size << ">!";
PIINTROSPECTION_CONTAINER_USED(sizeof(T))
elementNew(pid_data + pid_start + index, v); elementNew(pid_data + pid_start + index, v);
return *this; return *this;
} }
@@ -330,6 +339,7 @@ private:
return (1 << t); return (1 << t);
} }
inline void newT(T * dst, const T * src, size_t s) { 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) for (size_t i = 0; i < s; ++i)
elementNew(dst + i, src[i]); elementNew(dst + i, src[i]);
} }
@@ -346,6 +356,7 @@ private:
else pid_tdata = (T*)(realloc(pid_tdata, s * sizeof(T))); else pid_tdata = (T*)(realloc(pid_tdata, s * sizeof(T)));
}*/ }*/
inline void deleteT(T * d, size_t sz) { inline void deleteT(T * d, size_t sz) {
PIINTROSPECTION_CONTAINER_UNUSED(sz*sizeof(T))
//std::cout << " ~[("<<this<<")deleteT " << std::dec << sz << " elements " << " start " << pid_start << std::hex << " 0x" << (llong)d << " ... <" << std::endl; //std::cout << " ~[("<<this<<")deleteT " << std::dec << sz << " elements " << " start " << pid_start << std::hex << " 0x" << (llong)d << " ... <" << std::endl;
if ((uchar*)d != 0) { if ((uchar*)d != 0) {
for (size_t i = 0; i < sz; ++i) for (size_t i = 0; i < sz; ++i)
@@ -407,6 +418,7 @@ private:
size_t as = asize(pid_start + new_size); size_t as = asize(pid_start + new_size);
if (as != pid_rsize) { if (as != pid_rsize) {
//printf("(%p) realloc %d -> %d (%p)\n", this, pid_rsize, as, pid_data); //printf("(%p) realloc %d -> %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_data = (T*)(realloc(pid_data, as*sizeof(T)));
pid_rsize = as; pid_rsize = as;
//printf("(%p) realloc done (%p)\n", this, pid_data); //printf("(%p) realloc done (%p)\n", this, pid_data);
@@ -425,6 +437,7 @@ private:
T * td = newRaw(as); T * td = newRaw(as);
ssize_t ns = pid_start + as - pid_rsize; 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); //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) { 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); //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)); memcpy(td + ns, pid_data + pid_start, pid_size * sizeof(T));

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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();
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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<int, ThreadInfo> 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

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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);}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#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

View File

@@ -19,7 +19,7 @@
#include "pithread.h" #include "pithread.h"
#include "pisystemtests.h" #include "pisystemtests.h"
#include "piintrospection.h" #include "piintrospection_proxy.h"
#include <signal.h> #include <signal.h>
#ifdef WINDOWS #ifdef WINDOWS
void __PISetTimerResolution() {if (setTimerResolutionAddr == NULL) return; ULONG ret; setTimerResolutionAddr(1, TRUE, &ret);} void __PISetTimerResolution() {if (setTimerResolutionAddr == NULL) return; ULONG ret; setTimerResolutionAddr(1, TRUE, &ret);}
@@ -187,7 +187,7 @@ bool PIThread::startOnce() {
void PIThread::terminate() { void PIThread::terminate() {
if (thread == 0) return; if (thread == 0) return;
PIINTROSPECTION->unregisterThread(tid()); PIINTROSPECTION_UNREGISTER_THREAD(tid());
terminating = running_ = false; terminating = running_ = false;
tid_ = -1; tid_ = -1;
//piCout << "terminate" << thread; //piCout << "terminate" << thread;
@@ -219,7 +219,7 @@ __THREAD_FUNC__ PIThread::thread_function(void * t) {
__PISetTimerResolution(); __PISetTimerResolution();
#endif #endif
PIThread & ct = *((PIThread * )t); 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.running_ = true;
if (ct.lockRun) ct.mutex_.lock(); if (ct.lockRun) ct.mutex_.lock();
ct.begin(); ct.begin();
@@ -251,7 +251,7 @@ __THREAD_FUNC__ PIThread::thread_function(void * t) {
ct.tid_ = -1; ct.tid_ = -1;
//cout << "thread " << t << " exiting ... " << endl; //cout << "thread " << t << " exiting ... " << endl;
//piCout << "pthread_exit" << ct.thread; //piCout << "pthread_exit" << ct.thread;
PIINTROSPECTION->unregisterThread(ct.tid()); PIINTROSPECTION_UNREGISTER_THREAD(ct.tid());
#ifndef WINDOWS #ifndef WINDOWS
pthread_detach(ct.thread); pthread_detach(ct.thread);
ct.thread = 0; ct.thread = 0;
@@ -276,7 +276,7 @@ __THREAD_FUNC__ PIThread::thread_function_once(void * t) {
__PISetTimerResolution(); __PISetTimerResolution();
#endif #endif
PIThread & ct = *((PIThread * )t); 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.running_ = true;
ct.begin(); ct.begin();
ct.started(); ct.started();
@@ -290,7 +290,7 @@ __THREAD_FUNC__ PIThread::thread_function_once(void * t) {
ct.tid_ = -1; ct.tid_ = -1;
//cout << "thread " << t << " exiting ... " << endl; //cout << "thread " << t << " exiting ... " << endl;
//piCout << "pthread_exit" << ct.thread; //piCout << "pthread_exit" << ct.thread;
PIINTROSPECTION->unregisterThread(ct.tid()); PIINTROSPECTION_UNREGISTER_THREAD(ct.tid());
#ifndef WINDOWS #ifndef WINDOWS
pthread_detach(ct.thread); pthread_detach(ct.thread);
ct.thread = 0; ct.thread = 0;