C++ Multithreading with pthread is blocking (including sockets)
- by Sebastian Büttner
I am trying to implement a multi threaded application with pthread.
I did implement a thread class which looks like the following and I call it later twice (or even more), but it seems to block instead of execute the threads parallel.
Here is what I got until now:
The Thread Class is an abstract class which has the abstract method "exec" which should contain the thread code in a derive class (I did a sample of this, named DerivedThread)
Thread.hpp
#ifndef THREAD_H_
#define THREAD_H_
#include <pthread.h>
class Thread {
public:
Thread();
void start();
void join();
virtual int exec() = 0;
int exit_code();
private:
static void* thread_router(void* arg);
void exec_thread();
pthread_t pth_;
int code_;
};
#endif /* THREAD_H_ */
And Thread.cpp
#include <iostream>
#include "Thread.hpp"
/*****************************/
using namespace std;
Thread::Thread(): code_(0) {
cout << "[Thread] Init" << endl;
}
void Thread::start() {
cout << "[Thread] Created Thread" << endl;
pthread_create( &pth_,
NULL,
Thread::thread_router,
reinterpret_cast<void*>(this));
}
void Thread::join() {
cout << "[Thread] Join Thread" << endl;
pthread_join(pth_, NULL);
}
int Thread::exit_code() {
return code_;
}
void Thread::exec_thread() {
cout << "[Thread] Execute" << endl;
code_ = exec();
}
void* Thread::thread_router(void* arg) {
cout << "[Thread] exec_thread function in thread" << endl;
reinterpret_cast<Thread*>(arg)->exec_thread();
return NULL;
}
DerivedThread.hpp
#include "Thread.hpp"
class DerivedThread : public Thread {
public:
DerivedThread();
virtual ~DerivedThread();
int exec();
void Close() = 0;
DerivedThread.cpp
[...]
#include "DerivedThread.cpp"
[...]
int DerivedThread::exec() {
//code to be executed
do {
cout << "Thread executed" << endl;
usleep(1000000);
} while (true); //dummy, just to let it run for a while
}
[...]
Basically, I am calling this like the here:
DerivedThread *thread;
cout << "Creating Thread" << endl;
thread = new DerivedThread();
cout << "Created thread, starting..." << endl;
thread->start();
cout << "Started thread" << endl;
cout << "Creating 2nd Thread" << endl;
thread = new DerivedThread();
cout << "Created 2nd thread, starting..." << endl;
thread->start();
cout << "Started 2nd thread" << endl;
What is working great if I am only starting one of these Threads , but if I start multiple which should run together (not synced, only parallel) . But I discovered, that the thread is created, then as it tries to execute it (via start) the problem seems to block until the thread has closed. After that the next Thread is processed.
I thought that pthread would do it unblocked for me, so what did I wrong?
A sample output might be:
Creating Thread
[Thread] Thread Init
Created thread, starting...
[Thread] Created thread
[Thread] exec_thread function in thread
[Thread] Execute
Thread executed
Thread executed
Thread executed
Thread executed
Thread executed
Thread executed
Thread executed
....
Until Thread 1 is not terminated, a Thread 2 won't be created not executed.
The process above is executed in an other class. Just for the information: I am trying to create a multi threaded server. The concept is like this:
MultiThreadedServer Class has a main loop, like this one:
::inet::ServerSock *sock; //just a simple self made wrapper class for sockets
DerivedThread *thread;
for (;;) {
sock = new ::inet::ServerSock();
this->Socket->accept( *sock );
cout << "Creating Thread" << endl; //Threads (according to code sample above)
thread = new DerivedThread(sock); //I did not mentoine the parameter before as it was not neccesary, in fact, I pass the socket handle with the connected socket to the thread
cout << "Created thread, starting..." << endl;
thread->start();
cout << "Started thread" << endl;
}
So I thought that this would loop over and over and wait for new connections to accept. and when a new client arrives, I am creating a new thread and give the thread the connected socket as a parameter.
In the DerivedThread::exec I am doing the handling for the connected client. Like:
[...]
do {
[...]
if (this-sock_-read( Buffer, sizeof(PacketStruc) ) 0) {
cout << "[Handler_Base] Recv Packet" << endl;
//handle the packet
} else {
Connected = false;
}
delete Buffer;
} while ( Connected );
So I loop in the created thread as long as the client keeps the connection.
I think, that the socket may cause the blocking behaviour.
Edit:
I figured out, that it is not the read() loop in the DerivedThread Class as I simply replaced it with a loop over a simple cout-usleep part. It did also only execute the first one and after first thread finished, the 2nd one was executed.
Many thanks and best regards,
Sebastian