Threading (Join and Detach)

Hello out there,

i program a multiclient instant messager server to improve my knowledge in using sockets and threads. At time i have for each client a thread, that is listening for incoming data and an other thread, that proceeds this data. The "Data Proceeding Thread => dpt" is proceeding a queue of tasks and each client thread can add new tasks into this queue. And here i have had an idea:

I want the current client thread to join the dpt, because while the task is in the queue this thread just sleeps and waits. Each client object pointer has a pointer to the clients thread and each client pointer is passed to the task struct, so i can access the client in my dpt thread.

For better understanding:
//While runnjing in the client_thread just call dpt->join()
client_thread->join(dpt)
//dpt->doTask
dpt->client->client_thread->detach()

While running the program, this do not work. Is it possible to do something like this or should i use the good old semaphores?
Last edited on
1) Are you using std::thread or some other threading library?

What are you trying to do here. Join and detach are two mutually exclusive operations:
joing makes current thread wait untill other will finish.
Detach detaches thread of execution from std::thread object making it run in background. You still need to make sure that it will finish before your program terminates or it will cause undefined behavior.
In both cases std::thread objects becomes unjoinable, allowing to destroy it safely.
1. Yes, i am using the std::thread.

I want, that the client_thread waits but not until the other is finished, the other thread should detach the client_thread and proceed => the client_thread should proceed up here too.
Last edited on
join does not take parameter. I suppose it is your own function which is defined like
1
2
3
4
void /*...*/join(std::thread* tr)
{
    tr->join();
}
Is this correct?
If it is, client_thread->join(dpt); will make this thread wait for dpt finish, and not current_thread
Sry, i wrote it a bit to missunderstandable, i mean it like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Client {
...
    thread client_thread;
}

struct Task {
    char methodId;
    Client *c;
}

class MethodParser{
    queue<Task*> queue;
    thread *worker;

    void addTask(char methodId, Client *c); //Creates a new Task and pushs him into queue
    void joinWorker(){
        this->worker->join();
    }

    void work(){ //executed by worker thread.
        while(...){
            while(!this->queue.empty()){
                Task *t = this->queue.front();
                this->queue.pop();
                // ...        Parse Method (not interesting)
                t->c->client_thread->detach();
                delete t;
            }
        }
    }
}

class Listener {
...
    list<thread*> client_threads;
    list<client*> clients;
    MethodParser *parser;

    void listen(client* c){ //executed by each client_thread
        while(c->isConnected()){
            char methodId = c->readByte();
            this->parser->addTask(methodId, c);
            this->parser->joinWorker();
        }
    }
}
Last edited on
There is a problem:
1
2
3
4
5
while(c->isConnected()){
    char methodId = c->readByte();
    this->parser->addTask(methodId, c);
    this->parser->joinWorker();
}
1) There is no sense to call joinWorker in a loop. You can only call join once on a thread. This code makes corresponding client_thread wait until worker finishes.

2) t->c->client_thread->detach(); detaching affects only std::thread object. It does not affect thread of execution itself, so any blocked client thread will still wait for worker to completely finish execution.
Ah ok,
and the worker is an endless loop, so sh** :D, now i understand it.

An other way is to change the worker loop to:
1
2
3
4
5
6
7
8
void work(){ //executed by worker thread.
    while(!this->queue.empty()){
        Task *t = this->queue.front();
        this->queue.pop();
        // ...        Parse Method (not interesting)
        delete t;
    }
}


and start a new worker thread each time a new task will be add to the queue without that there is a working worker. In this case all client_threads will wait until the queue is finished (in worst case ALL client_threads). The result is, that each client has the same "priority".

An other way is to "lock" the client, so the client_thread waits until the client will be unlocked (sth. like semaphores).

Which way would you recomend me?
Last edited on
Or use some other methods of interthread communication. You can use mix of packaged task/future/promise to communicate between worker/clients (<maybe> packaged task is saved in queue, client get future and waits on it, worker fulfills promise when it can, enabling corresponding client thread)
http://en.cppreference.com/w/cpp/thread/packaged_task
http://en.cppreference.com/w/cpp/thread/future

Or use asynchronous function calls:
http://en.cppreference.com/w/cpp/thread/async

Pick whechever will be more suitable to you
Wow, thank you for this very good help :)
I don't understand this 3 ways, but i will read more about it.
Topic archived. No new replies allowed.