28.07.2020 21:23 Juha Nieminen kirjutas:
> Paavo Helde <
ees...@osa.pri.ee> wrote:
>> If you want to create your own explicit thread pool, this is IMO best
>> organized by a message queue.
>
> That gives me the idea for the project I'm thinking that, indeed, maybe
> it's easier if the threads themselves just find out by themselves what
> is the next task to perform (in this case they all do the same kind task,
> just with different parameters).
Well, that's what the queue is about. The worker thread finds out its
task by extracting an entry from the queue.
> The only thing I need to figure out is to have the threads idle until
> the main thread has written the required parameters to a common struct
> and then notify all the threads to start taking tasks from there.
For each task, the main thread would fill out a struct with parameters,
pushes it into the queue under a mutec lock and call
conditionvar.notify_one().
Each worker thread would lock the queue mutex and call
conditionvar.wait() (which unlocks the mutex behind the scenes while
waiting). When the wait call returns, the worker thread checks if there
is something in the queue (as there can be spurious wakeups), if so,
pops a task from the queue and releases the mutex. That's it.
>
> Then I also need to figure out how to make the threads notify the
> main thread when all the tasks are done.
>
> I wonder if this should be done with std::future or with
> std::condition_variable.
This can be done by another queue (containing another mutex and another
condition variable). When ready, each thread would push the result to
the result queue and notify its condition variable. The main thread
waits on this condition variable, when notified, extracts the result
from the queue, puts it into the right place and increments the result
count. When all results are received, it stops waiting.
Your aim is to minimize the time spent under mutex locks when
pushing/popping queues. This can be achieved by using move or swap in
those operations. Queue-based thread synchronization is great in that
only these cheap move/swap operations need to be protected, and
otherwise the threads can run by their own without any need to worry
about MT safety or synchronization.