Hi there,
I'm trying to use this thread-pool "LIB" and before using it, I wanted to make some stress tests on it to identify its limit, its hardening and reliability.
I wrote a really short main function and set a small amount of thread (1) with also a small file queue size (2). The behavior I can see is really strange : Some destructor may be called before constructor :huh: and the same input may be treated by several tasks
Here is the small main.cpp :
#include <iostream>
#include <regex>
#include <vector>
#include <signal.h>
#include <unistd.h>
// #include "logger.h"
#include <future>
#include <utility>
#include "thread_pool.hpp"
static volatile bool g_theEnd = false ;
#define DEBUG(...) { printf(__VA_ARGS__) ; printf("\n") ; }
#define INFO(...) { printf(__VA_ARGS__) ; printf("\n") ; }
#define WARNING(...) { printf(__VA_ARGS__) ; printf("\n") ; }
#define ERROR(...) { printf(__VA_ARGS__) ; printf("\n") ; }
#define LOG_INIT(a)
#define SET_LOG_LEVEL(a)
#define LOG_END()
//
//
//
void cleanup(void)
{
// Ask the threads to give up
g_theEnd = true ;
INFO("Stop test-thread-pool") ;
LOG_END() ;
}
//
//
//
class NgapMessageDecode
{
public:
NgapMessageDecode(int fd) : m_fd(fd)
{
DEBUG("Constructor %.8ld, fd=%.2d", this, fd) ;
}
virtual ~NgapMessageDecode()
{
DEBUG("Destructor %.8ld, fd=%.2d", this, m_fd) ;
}
void operator()()
{
DEBUG("Decode %.2d, this=%ld, thread=%.8ld", m_fd, this, pthread_self()) ;
// sleep(1) ;
}
private:
// std::promise<void> * m_waiter ;
int m_fd ;
};
int main(int argc, char * argv[])
{
LOG_INIT("test-thread-pool") ;
SET_LOG_LEVEL(_LOG_DEBUG) ;
INFO("%s", "") ;
INFO("Start test-thread-pool") ;
tp::ThreadPoolOptions threadPoolOption ;
threadPoolOption.setThreadCount(1) ;
threadPoolOption.setQueueSize(2) ;
tp::ThreadPool threadPool(threadPoolOption);
for(int i=0; i<100; i++)
{
try
{
threadPool.post(NgapMessageDecode(i)) ;
}
catch(std::runtime_error & e)
{
std::cout << e.what() << std::endl ;
}
}
sleep(1) ;
cleanup() ;
return 0 ;
}
The output is :
Start test-thread-pool
Constructor 140734462742560, fd=00
Destructor 140734462742176, fd=00
Destructor 140734462742560, fd=00
Constructor 140734462742560, fd=01
Destructor 140734462742176, fd=01
Destructor 140734462742560, fd=01
Constructor 140734462742560, fd=02
Destructor 140734462742560, fd=02
thread pool queue is full
Constructor 140734462742560, fd=03
Destructor 140734462742560, fd=03
thread pool queue is full
Constructor 140734462742560, fd=04
Destructor 140734462742560, fd=04
thread pool queue is full
How can the Destructor 140734462742176, fd=00 (line2) can be called before the constructor ?
More over, this same Destructor refers to the object where fd==00 whereas the corresponding constructor below refers to fd==01
Thus, how can I got the sequence described in the 3 first lines : Constructor / Destructor / Destructor with the same FD==00
So, I probably missed something or at least misunderstood how I'm supposed to use this "LIB" but I can't find out what's the good practice :/
Branch used : master
I can't use the branch round-robin-stealing 'cause it refers to std::exchange that is defined in C++14 and I must stay in C++11
Command to build the main application listed above, to facilitate :
g++ -c -DLOG -I<path_to_thread-pool-cpp>/include/thread_pool -Wall -Wextra -g -std=c++11 -o main.o main.cpp
g++ -g -o test-thread-pool main.o -lpthread
All kind of help would be appreciated :+1: