|
Scroom 0.14-49-gb7ae7a6d
|

Public Types | |
| using | Ptr = std::shared_ptr< PrivateData > |
Static Public Member Functions | |
| static Ptr | create (bool completeAllJobsBeforeDestruction) |
Public Attributes | |
| unsigned int | jobcount {0} |
| boost::mutex | mut |
| bool | alive {true} |
| boost::condition_variable | cond |
| std::map< int, std::queue< Job > > | jobs |
| bool | completeAllJobsBeforeDestruction |
| Queue::Ptr | defaultQueue |
Private Member Functions | |
| PrivateData (bool completeAllJobsBeforeDestruction) | |
| ThreadPool::PrivateData. | |
Data needed by the threads to do their work.
It used to be that ThreadPool destruction blocked until the last thread finished, which was a major cause of deadlock when a ThreadPool thread held the last reference to its ThreadPool.
To fix this, it becomes necessary to destroy ThreadPool objects, even though there still are running threads. These threads need access to some data, in order to complete any currently running jobs, and in order to determine that they, themselves should finish. Objects of this class contain that data. Both ThreadPool objects, as well as threads running in a ThreadPool, will have a reference to objects of this class.
Waiting for all threads to finish is now done by the ThreadWaiter class, which has only one instance, declared static. Hence, it is always destroyed on the main thread, which never is part of any threadpool. Hence, the deadlock is avoided.
| using ThreadPool::PrivateData::Ptr = std::shared_ptr<PrivateData> |
|
explicitprivate |
|
static |
| bool ThreadPool::PrivateData::alive {true} |
true if this ThreadPool is not in the process of being destroyed
| bool ThreadPool::PrivateData::completeAllJobsBeforeDestruction |
If true, this ThreadPool completes all jobs before being destroyed.
If it is false, the ThreadPool will remove unfinished jobs from the queue without executing them, and then self-destruct.
| boost::condition_variable ThreadPool::PrivateData::cond |
For signalling newly queued jobs
| Queue::Ptr ThreadPool::PrivateData::defaultQueue |
Reference to the default Queue.
If we don't store a reference to the default Queue here, then objects calling schedule() without a Queue argument (hence using the default Queue), may find that they are themselves holding the last reference to the ThreadPool::defaultQueue() object. That could result in deadlock, if the thread doing the scheduling is itself a ThreadPool thread. Recall that destroying a Queue blocks until any currently running tasks are finished, and hence a task would be infinitely waiting for itself to finish.
| unsigned int ThreadPool::PrivateData::jobcount {0} |
current number of tasks in ThreadPool::jobs
| std::map<int, std::queue<Job> > ThreadPool::PrivateData::jobs |
Jobs that remain to be executed
The map contains for each priority that has jobs, a queue containing those jobs. Once a queue is empty, it is removed from the map. If a new job for that priority is scheduled, it is added again.
| boost::mutex ThreadPool::PrivateData::mut |
For protecting ThreadPool::jobs