diff --git a/slsDetectorSoftware/Makefile b/slsDetectorSoftware/Makefile index 534e097a4..17422ee95 100644 --- a/slsDetectorSoftware/Makefile +++ b/slsDetectorSoftware/Makefile @@ -10,12 +10,12 @@ CFLAGS= -g -DC_ONLY -fPIC DFLAGS= -g -DDACS_INT -INCLUDES?= -IcommonFiles -IslsDetector -I../slsReceiverSoftware/MySocketTCP -IusersFunctions -ImultiSlsDetector -IslsDetectorUtils -IslsDetectorCommand -IslsDetectorAnalysis -IslsReceiverInterface -I../slsReceiverSoftware/include -I$(ASM) +INCLUDES?= -IcommonFiles -IslsDetector -I../slsReceiverSoftware/MySocketTCP -IusersFunctions -ImultiSlsDetector -IslsDetectorUtils -IslsDetectorCommand -IslsDetectorAnalysis -IslsReceiverInterface -I../slsReceiverSoftware/include -IthreadFiles -I$(ASM) #EPICSFLAGS=-D EPICS -I/usr/local/epics/base/include/ -I /usr/local/epics/base/include/os/Linux/ -L /usr/local/epics/base/lib/$(EPICS_HOST_ARCH) -Wl,-R/usr/local/epics/base/lib/$(EPICS_HOST_ARCH) -lca -lCom -SRC_CLNT=slsDetectorAnalysis/fileIO.cpp usersFunctions/usersFunctions.cpp slsDetector/slsDetectorUtils.cpp slsDetector/slsDetectorCommand.cpp slsDetectorAnalysis/angularConversion.cpp slsDetectorAnalysis/angularConversionStatic.cpp slsDetectorAnalysis/energyConversion.cpp slsDetector/slsDetectorActions.cpp slsDetectorAnalysis/postProcessing.cpp slsDetector/slsDetector.cpp multiSlsDetector/multiSlsDetector.cpp slsDetectorAnalysis/postProcessingFuncs.cpp slsReceiverInterface/receiverInterface.cpp slsDetector/slsDetectorUsers.cpp #../slsReceiverSoftware/MySocketTCP/MySocketTCP.cpp +SRC_CLNT=slsDetectorAnalysis/fileIO.cpp usersFunctions/usersFunctions.cpp slsDetector/slsDetectorUtils.cpp slsDetector/slsDetectorCommand.cpp slsDetectorAnalysis/angularConversion.cpp slsDetectorAnalysis/angularConversionStatic.cpp slsDetectorAnalysis/energyConversion.cpp slsDetector/slsDetectorActions.cpp slsDetectorAnalysis/postProcessing.cpp slsDetector/slsDetector.cpp multiSlsDetector/multiSlsDetector.cpp slsDetectorAnalysis/postProcessingFuncs.cpp slsReceiverInterface/receiverInterface.cpp slsDetector/slsDetectorUsers.cpp threadFiles/CondVar.cpp threadFiles/Mutex.cpp threadFiles/ThreadPool.cpp #../slsReceiverSoftware/MySocketTCP/MySocketTCP.cpp $(info ) diff --git a/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp b/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp index 5ac484452..9b54ec3c7 100644 --- a/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp +++ b/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.cpp @@ -16,6 +16,8 @@ ID: $Id$ #include "multiSlsDetectorClient.h" #include "postProcessingFuncs.h" #include "usersFunctions.h" +#include "ThreadPool.h" + #include #include #include @@ -265,13 +267,50 @@ multiSlsDetector::multiSlsDetector(int id) : slsDetectorUtils(), shmId(-1) getNMods(); getMaxMods(); + if(createThreadPool() == FAIL) + exit(-1); + } multiSlsDetector::~multiSlsDetector() { //removeSlsDetector(); - + destroyThreadPool(); } + +int multiSlsDetector::createThreadPool(){ + if(threadpool){ + threadpool->destroy_threadpool(); + threadpool=0; + } + if(thisMultiDetector->numberOfDetectors < 1){ + cout << "No detectors attached to create threadpool" << endl; + return OK; + } + threadpool = new ThreadPool(thisMultiDetector->numberOfDetectors); + switch(threadpool->initialize_threadpool()){ + case 0: + cerr << "Failed to initialize thread pool!" << endl; + return FAIL; + case 1: + cout << "Not initializing threads, only one detector" << endl; + break; + default: + cout << "Initialized Threadpool" << endl; + break; + } + return OK; +} + +void multiSlsDetector::destroyThreadPool(){ + if(threadpool){ + threadpool->destroy_threadpool(); + threadpool=0; + cout<<"Destroyed Threadpool"<numberOfDetectors; @@ -1088,7 +1127,7 @@ int multiSlsDetector::setThresholdEnergy(int e_eV, int pos, detectorSettings ise slsDetectorDefs::detectorSettings multiSlsDetector::getSettings(int pos) { int i, posmin, posmax; - detectorSettings ret1=GET_SETTINGS, ret; + int ret1=-100, ret=-1; if (pos<0) { posmin=0; @@ -1098,21 +1137,49 @@ slsDetectorDefs::detectorSettings multiSlsDetector::getSettings(int pos) { posmax=pos+1; } - for (i=posmin; igetSettings(); - if(detectors[i]->getErrorMask()) - setErrorMask(getErrorMask()|(1<(&slsDetector::getSettings, + detectors[idet],-1,iret[idet])); + threadpool->add_task(task); + } + } + threadpool->wait_for_tasks_to_complete(); + for(int idet=posmin; idetgetSettings(); + if(detectors[i]->getErrorMask()) + setErrorMask(getErrorMask()|(1<currentSettings=ret1; - return ret1; + thisMultiDetector->currentSettings=(detectorSettings)ret; + return (detectorSettings)ret; } slsDetectorDefs::detectorSettings multiSlsDetector::setSettings(detectorSettings isettings, int pos) { diff --git a/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.h b/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.h index 311810396..6bfb6adb3 100644 --- a/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.h +++ b/slsDetectorSoftware/multiSlsDetector/multiSlsDetector.h @@ -16,6 +16,7 @@ ID: $Id$ #include "slsDetectorUtils.h" class slsDetector; +class ThreadPool; //#include "sls_detector_defs.h" @@ -240,6 +241,14 @@ class multiSlsDetector : public slsDetectorUtils { /** destructor */ virtual ~multiSlsDetector(); + /** + * Creates all the threads in the threadpool + \returns OK or FAIL + */ + int createThreadPool(); + + /** destroys all the threads in the threadpool */ + void destroyThreadPool(); /** frees the shared memory occpied by the sharedMultiSlsDetector structure */ int freeSharedMemory() ; @@ -1362,6 +1371,8 @@ class multiSlsDetector : public slsDetectorUtils { /** Shared memory structure */ sharedMultiSlsDetector *thisMultiDetector; + private: + ThreadPool* threadpool; diff --git a/slsDetectorSoftware/threadFiles/CondVar.cpp b/slsDetectorSoftware/threadFiles/CondVar.cpp new file mode 100644 index 000000000..2feff962f --- /dev/null +++ b/slsDetectorSoftware/threadFiles/CondVar.cpp @@ -0,0 +1,17 @@ +#include "CondVar.h" + +CondVar::CondVar() { + pthread_cond_init(&m_cond_var, NULL); +} +CondVar::~CondVar() { + pthread_cond_destroy(&m_cond_var); +} +void CondVar::wait(pthread_mutex_t* mutex) { + pthread_cond_wait(&m_cond_var, mutex); +} +void CondVar::signal() { + pthread_cond_signal(&m_cond_var); +} +void CondVar::broadcast() { + pthread_cond_broadcast(&m_cond_var); +} diff --git a/slsDetectorSoftware/threadFiles/CondVar.h b/slsDetectorSoftware/threadFiles/CondVar.h new file mode 100644 index 000000000..b823ef31d --- /dev/null +++ b/slsDetectorSoftware/threadFiles/CondVar.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "Global.h" + +using namespace std; + +class CondVar { +public: + + CondVar(); + ~CondVar(); + void wait(pthread_mutex_t* mutex); + void signal(); + void broadcast(); + +private: + pthread_cond_t m_cond_var; +}; diff --git a/slsDetectorSoftware/threadFiles/Global.h b/slsDetectorSoftware/threadFiles/Global.h new file mode 100644 index 000000000..2596df0c0 --- /dev/null +++ b/slsDetectorSoftware/threadFiles/Global.h @@ -0,0 +1,6 @@ +#pragma once + +const int DEFAULT_POOL_SIZE = 10; +const int MAX_SINGLES = 5; +const int STARTED = 0; +const int STOPPED = 1; diff --git a/slsDetectorSoftware/threadFiles/Makefile b/slsDetectorSoftware/threadFiles/Makefile new file mode 100644 index 000000000..19b5b40e4 --- /dev/null +++ b/slsDetectorSoftware/threadFiles/Makefile @@ -0,0 +1,21 @@ +OBJPATH=bin/obj +EXAMPLEPATH=bin/example + +all: + g++ CondVar.cpp -lpthread -c -g -o $(OBJPATH)/CondVar.o + g++ Mutex.cpp -lpthread -c -g -o $(OBJPATH)/Mutex.o + #g++ Task.cpp -lpthread -c -g -o $(OBJPATH)/Task.o + g++ ThreadPool.cpp -lpthread -c -g -o $(OBJPATH)/ThreadPool.o + g++ Multi.cpp -lpthread -c -g -o $(OBJPATH)/Multi.o + #g++ $(OBJPATH)/CondVar.o $(OBJPATH)/Mutex.o $(OBJPATH)/Task.o $(OBJPATH)/ThreadPool.o threadpool_test.cpp Single.cpp Multi.cpp -lpthread -I . -g -o $(EXAMPLEPATH)threadpool_test + g++ $(OBJPATH)/CondVar.o $(OBJPATH)/Mutex.o $(OBJPATH)/ThreadPool.o threadpool_test.cpp Single.cpp Multi.cpp -lpthread -I . -g -o $(EXAMPLEPATH)threadpool_test + +#all: +# g++ threadpool.cpp -lpthread -fpic -c -o bin/obj/threadpool.o +# g++ -L./bin bin/obj/threadpool.o -lpthread threadpool_test.cpp -o bin/example/threadpool_test + +#threadpool: +# g++ threadpool.cpp -lpthread -fpic -c -o bin/obj/threadpool.o +# g++ -shared -fPIC bin/obj/threadpool.o -o bin/lib/libthreadpool.so +#example: +# g++ -L./bin/lib -lthreadpool threadpool_test.cpp -o threadpool_test diff --git a/slsDetectorSoftware/threadFiles/Multi.cpp b/slsDetectorSoftware/threadFiles/Multi.cpp new file mode 100644 index 000000000..7740de5fe --- /dev/null +++ b/slsDetectorSoftware/threadFiles/Multi.cpp @@ -0,0 +1,197 @@ +#include "Multi.h" +#include "Single.h" +#include "ThreadPool.h" + + + +#include +#include +#include +#include +using namespace std; + +char ans[1000]; +int threadflag = 1; + +Multi::Multi() { + numSingles = 1; + threadpool = 0; + for(int i=0;idestroy_threadpool(); + threadpool=0; + } + if(numSingles > 0) + threadpool = new ThreadPool(numSingles); + switch(threadpool->initialize_threadpool()){ + case -1: + cerr << "Failed to initialize thread pool!" << endl; + return 0; + case 0: + cout << "Not initializing threads, only one detector" << endl; + break; + default: + cout << "Initialized Threadpool" << endl; + break; + } + return 1; +} + +int Multi::destroyThreadPool(){ + if(threadpool){ + threadpool->destroy_threadpool(); + threadpool=0; + cout<<"Destroyed Threadpool"<* binder = + // new func_t(&Single::printNumber,singles[i],inum,iret[i]); + Task* task = new Task(new func_t(&Single::printNumber,singles[i],inum,iret[i])); + threadpool->add_task(task); + } + threadpool->wait_for_tasks_to_complete(); + + + for(int i=0;i1){ + string* sret[numSingles]; + + + for(int i=0;i* binder = + new func_t(&Single::printString,singles[i],s,sret[i]); + Task* task = new Task(binder); + threadpool->add_task(task); + } + threadpool->wait_for_tasks_to_complete(); + for(int i=0;iprintString(s); + if(ret=="error") + ret = ret1; + else if (ret != ret1) + ret = "sss"; + } + } + return ret; +} + +char* Multi::printCharArray(char a[]){ + string ret="error", ret1="sss"; + + if(numSingles>1){ + string* sret[numSingles]; + + for(int i=0;i* binder = + new func_t (&Single::printCharArray,singles[i],a,sret[i]); + Task* task = new Task(binder); + threadpool->add_task(task); + } + threadpool->wait_for_tasks_to_complete(); + + for(int i=0;iprintCharArray(a); + if(ret=="error") + ret = ret1; + else if (ret != ret1) + ret = "sss"; + } + } + strcpy(ans,ret.c_str()); + return ans; +} diff --git a/slsDetectorSoftware/threadFiles/Multi.h b/slsDetectorSoftware/threadFiles/Multi.h new file mode 100644 index 000000000..b7216c579 --- /dev/null +++ b/slsDetectorSoftware/threadFiles/Multi.h @@ -0,0 +1,36 @@ +#pragma once + + +#include "Global.h" + +#include +using namespace std; + +class Single; +class ThreadPool; + +class Multi { +public: + + Multi(); + ~Multi(); + + string executeCommand(int argc,char* argv[]); + + int printNumber(int inum); + string printString(string s); + char* printCharArray(char a[]); + + int createThreadPool(); + int destroyThreadPool(); + +protected: + Single* singles[MAX_SINGLES]; + int numSingles; + ThreadPool* threadpool; + + + +}; + + diff --git a/slsDetectorSoftware/threadFiles/Mutex.cpp b/slsDetectorSoftware/threadFiles/Mutex.cpp new file mode 100644 index 000000000..3f7cdca25 --- /dev/null +++ b/slsDetectorSoftware/threadFiles/Mutex.cpp @@ -0,0 +1,26 @@ +#include "Mutex.h" + +Mutex::Mutex() { + pthread_mutex_init(&m_lock, NULL); + is_locked = false; +} + +Mutex::~Mutex() { + while(is_locked); + unlock(); // Unlock Mutex after shared resource is safe + pthread_mutex_destroy(&m_lock); +} + +void Mutex::lock() { + pthread_mutex_lock(&m_lock); + is_locked = true; +} + +void Mutex::unlock() { + is_locked = false; // do it BEFORE unlocking to avoid race condition + pthread_mutex_unlock(&m_lock); +} + +pthread_mutex_t* Mutex::get_mutex_ptr(){ + return &m_lock; +} diff --git a/slsDetectorSoftware/threadFiles/Mutex.h b/slsDetectorSoftware/threadFiles/Mutex.h new file mode 100644 index 000000000..a88df0d4e --- /dev/null +++ b/slsDetectorSoftware/threadFiles/Mutex.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "Global.h" + +using namespace std; + +class Mutex +{ +public: + Mutex(); + ~Mutex(); + void lock(); + void unlock(); + pthread_mutex_t* get_mutex_ptr(); + +private: + pthread_mutex_t m_lock; + volatile bool is_locked; +}; diff --git a/slsDetectorSoftware/threadFiles/Single.cpp b/slsDetectorSoftware/threadFiles/Single.cpp new file mode 100644 index 000000000..43b0ca14b --- /dev/null +++ b/slsDetectorSoftware/threadFiles/Single.cpp @@ -0,0 +1,37 @@ +#include "Single.h" + +#include +#include +using namespace std; + +char local_ans[1000]; + +Single::Single(int id) { + detID = id; + // cout<<"detID:"< +using namespace std; + +class Single { +public: + Single(int id); + ~Single(); + int getID(); + + int printNumber(int i); + string printString(string s); + char* printCharArray(char a[]); + +private: + int detID; + + int* someValue; + +}; + diff --git a/slsDetectorSoftware/threadFiles/Task.h b/slsDetectorSoftware/threadFiles/Task.h new file mode 100644 index 000000000..3f096382e --- /dev/null +++ b/slsDetectorSoftware/threadFiles/Task.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "Global.h" +#include "sls_detector_defs.h" + +#include +using namespace std; + +class slsDetector; + + +template +class func_t{ +public: + func_t(_Ret (_Class::*fn)(_Arg1),_Class* ptr,_Arg1 arg1, _Store* sto):m_fn(fn),m_ptr(ptr),m_arg1(arg1),m_store(sto){} + ~func_t() {} + + void operator()() const {*m_store = ((m_ptr->*m_fn)(m_arg1));} + +private: + _Class* m_ptr; + _Ret (_Class::*m_fn)(_Arg1); + _Arg1 m_arg1; + _Store* m_store; +}; + + +class Task: public virtual slsDetectorDefs{ +public: + Task(func_t * t):m_int1(t),m_string1(0),m_chararr1(0), + m_settings(0){}; + Task(func_t * t): m_int1(0),m_string1(t),m_chararr1(0), + m_settings(0){}; + Task(func_t * t):m_int1(0),m_string1(0),m_chararr1(t), + m_settings(0){}; + + + //settings + Task(func_t * t): + m_int1(0),m_string1(0),m_chararr1(0), + m_settings(t) + {}; + + ~Task(){} + + void operator()(){ + if(m_int1) (*m_int1)(); + else if(m_string1) (*m_string1)(); + else if(m_chararr1) (*m_chararr1)(); + else if(m_settings) (*m_settings)(); + } + +private: + func_t * m_int1; + func_t * m_string1; + func_t * m_chararr1; + func_t * m_settings; +}; + + diff --git a/slsDetectorSoftware/threadFiles/ThreadPool.cpp b/slsDetectorSoftware/threadFiles/ThreadPool.cpp new file mode 100644 index 000000000..bb5a06419 --- /dev/null +++ b/slsDetectorSoftware/threadFiles/ThreadPool.cpp @@ -0,0 +1,175 @@ +#include "ThreadPool.h" + + +ThreadPool::ThreadPool(int pool_size) : m_pool_size(pool_size) +{ + cout << "Constructed ThreadPool of size " << m_pool_size << endl; + m_tasks_loaded = false; + thread_started = false; + current_thread_number = -1; + number_of_ongoing_tasks = 0; +} + +ThreadPool::~ThreadPool() +{ + // Release resources + if (m_pool_state != STOPPED) { + destroy_threadpool(); + } +} + +// We can't pass a member function to pthread_create. +// So created the wrapper function that calls the member function +// we want to run in the thread. +extern "C" +void* start_thread(void* arg) +{ + ThreadPool* tp = (ThreadPool*) arg; + tp->execute_thread(); + return NULL; +} + +int ThreadPool::initialize_threadpool() +{ + if(m_pool_size == 1) + return m_pool_size; + + // TODO: COnsider lazy loading threads instead of creating all at once + m_pool_state = STARTED; + int ret = -1; + for (int i = 0; i < m_pool_size; i++) { + pthread_t tid; + thread_started = false; + current_thread_number = i; + ret = pthread_create(&tid, NULL, start_thread, (void*) this); + if (ret != 0) { + cerr << "pthread_create() failed: " << ret << endl; + return 0; + } + m_threads.push_back(tid); + while(!thread_started); + } + cout << m_pool_size << " threads created by the thread pool" << endl; + + return m_pool_size; +} + +int ThreadPool::destroy_threadpool() +{ if(m_pool_size == 1) + return 0; + //cout << "in destroying threadpool" << endl; + // Note: this is not for synchronization, its for thread communication! + // destroy_threadpool() will only be called from the main thread, yet + // the modified m_pool_state may not show up to other threads until its + // modified in a lock! + m_task_mutex.lock(); + m_pool_state = STOPPED; + m_task_mutex.unlock(); + /*cout << "Broadcasting STOP signal to all threads..." << endl;*/ + m_task_cond_var.broadcast(); // notify all threads we are shttung down + + int ret = -1; + for (int i = 0; i < m_pool_size; i++) { + void* result; + ret = pthread_join(m_threads[i], &result); + /*cout << "pthread_join() returned " << ret << ": " << strerror(errno) << endl;*/ + m_task_cond_var.broadcast(); // try waking up a bunch of threads that are still waiting + } + number_of_ongoing_tasks = 0; + /* cout << m_pool_size << " threads exited from the thread pool" << endl;*/ + return 0; +} + +void* ThreadPool::execute_thread() +{ + int ithread = current_thread_number; + thread_started = true; + Task* task = NULL; + m_tasks_loaded = false; + /*cout << "Starting thread " << pthread_self() << endl;*/ + while(true) { + // Try to pick a task + /*cout << "Locking: " << pthread_self() << endl;*/ + m_task_mutex.lock(); + + // We need to put pthread_cond_wait in a loop for two reasons: + // 1. There can be spurious wakeups (due to signal/ENITR) + // 2. When mutex is released for waiting, another thread can be waken up + // from a signal/broadcast and that thread can mess up the condition. + // So when the current thread wakes up the condition may no longer be + // actually true! + while ((m_pool_state != STOPPED) && (m_tasks.empty())) { + // Wait until there is a task in the queue + // Unlock mutex while wait, then lock it back when signaled + /* cout << "Unlocking and waiting: " << pthread_self() << endl;*/ + m_task_cond_var.wait(m_task_mutex.get_mutex_ptr()); + /* cout << "Signaled and locking: " << pthread_self() << endl;*/ + } + + // If the thread was woken up to notify process shutdown, return from here + if (m_pool_state == STOPPED) { + /* cout << "Unlocking and exiting: " << pthread_self() << endl;*/ + m_task_mutex.unlock(); + pthread_exit(NULL); + } + + task = m_tasks.front(); + m_tasks.pop_front(); + /*cout << "Unlocking: " << pthread_self() << endl;*/ + m_task_mutex.unlock(); + + //cout << "Executing thread " << pthread_self() << endl; + // execute the task + (*task)(); // could also do task->run(arg); + //cout << "Done executing thread " << pthread_self() << endl; + + m_all_tasks_mutex.lock(); + number_of_ongoing_tasks--; // cout<<"number_of_ongoing_tasks:"< +#include +#include +#include +#include +#include +#include +#include + +#include "Mutex.h" +#include "Task.h" +#include "CondVar.h" +#include "Global.h" + +using namespace std; + + +class ThreadPool +{ +public: + ThreadPool(int pool_size); + ~ThreadPool(); + int initialize_threadpool(); + int destroy_threadpool(); + void* execute_thread(); + int add_task(Task* task); + void wait_for_tasks_to_complete(); + +private: + int m_pool_size; + Mutex m_task_mutex; + CondVar m_task_cond_var; + std::vector m_threads; // storage for threads + std::deque m_tasks; + volatile int m_pool_state; + + Mutex m_all_tasks_mutex; + CondVar m_all_tasks_cond_var; + bool m_tasks_loaded; + bool thread_started; + int current_thread_number; + + //volatile uint64_t tasks_done_mask; + volatile int number_of_ongoing_tasks; +}; + diff --git a/slsDetectorSoftware/threadFiles/bin/examplethreadpool_test b/slsDetectorSoftware/threadFiles/bin/examplethreadpool_test new file mode 100755 index 000000000..621d57a47 Binary files /dev/null and b/slsDetectorSoftware/threadFiles/bin/examplethreadpool_test differ diff --git a/slsDetectorSoftware/threadFiles/threadpool_test.cpp b/slsDetectorSoftware/threadFiles/threadpool_test.cpp new file mode 100644 index 000000000..2dbd2c416 --- /dev/null +++ b/slsDetectorSoftware/threadFiles/threadpool_test.cpp @@ -0,0 +1,61 @@ +//#include "ThreadPool.h" + +//#include "threadpool.h" + +#include +#include + +#include "Multi.h" +using namespace std; + +//const int MAX_TASKS = 4; + +/* +void hello(void* arg) +{ + string* x = (string*) arg; + cout << "Hello: " << *x << endl; +// cout << "\n"; +} +*/ +int main(int argc, char* argv[]) +{ + + Multi* m = new Multi(); + cout<<"Answer:"<< m->executeCommand(argc,argv) << endl; + delete m; + /* + ThreadPool tp(2); + int ret = tp.initialize_threadpool(); + if (ret == -1) { + cerr << "Failed to initialize thread pool!" << endl; + return 0; + } +*/ + + +/* + for (int i = 0; i < MAX_TASKS; i++) { + cout<<"adding task:" <