ThreadPool
Engine/source/platform/threads/threadPool.h
Asynchronous work manager.
Classes:
A ThreadPool context defines a logical context in which WorkItems are being executed.
An action to execute on a worker thread from the pool.
Value wrapper for work items while placed on priority queue.
Public Types
WorkItemPtr
Protected Types
QueueType
Public Friends
struct
Protected Attributes
Number of work items that have not yet completed execution.
Number of worker threads spawned by the pool.
Number of worker threads in non-sleeping state.
Number of worker threads guaranteed to be non-blocking.
Semaphore used to wake up threads, if necessary.
List of worker threads.
Threaded priority queue for concurrent access by worker threads.
Protected Static Attributes
bool
Force all work items to execute on main thread; turns this into a single-threaded system.
Work queue for main thread; can be used to ping back work items to main thread that need processing that can only happen on main thread.
Public Functions
ThreadPool(const char * name, U32 numThreads)
Create a new thread pool with the given number of worker threads.
flushWorkItems(S32 timeOut)
For the global pool, it is very important to only ever call this function on the main thread and to let work items only ever come from the main thread.
Return the priority increment applied to work items on each passing of the update interval.
Return the interval in which item priorities are updated on the queue.
queueWorkItem(WorkItem * item)
Set the priority increment applied to work items on each update interval.
setQueueUpdateInterval(U32 milliSeconds)
Set the update interval of the work item queue to the given value.
waitForAllItems(S32 timeOut)
If you're using a non-global thread pool to parallelise some work, you may want to block until all the parallel work is complete.
Public Static Functions
bool &
GLOBAL()
Return the global thread pool singleton.
Process work items waiting on the main thread's work queue.
queueWorkItemOnMainThread(WorkItem * item)
Add a work item to the main thread's work queue.
Detailed Description
Asynchronous work manager.
Thread pooling allows to submit work items for background execution. Each work item will be placed on a queue and, based on a total priority ordering, executed when it has the highest priority and a worker thread becomes available.
note:Flushing is the simplest method to guarantee that no asynchronous operation is pending in a specific case (deletion of the target object being the most common case). However, when possible, avoid this situation and design your work items to operate independently, e.g. by having only a single point of access to data that may have disappeared in the meantime and putting a check around that single access so that the item will silently die when its target object has disappeared.The global pool maintains the invariant that only the main thread may submit items in order to be able to flush the item queue reliably from the main thread itself. If other threads were issuing items to the queue, the queue may never empty out and the main thread will deadlock.
The cleanest safe solution to this is to create a separate concurrently reference-counted structure that holds all interfacing state and functionality shared between a work item and its issueing code. This way the host object can safely disappear with the interfacing structure automatically being released once the last concurrent work item has been processed or discarded.
Public Types
typedef ThreadSafeRef< WorkItem > WorkItemPtr
Protected Types
typedef ThreadSafePriorityQueueWithUpdate< WorkItemWrapper, F32 > QueueType
Public Friends
Protected Attributes
String mName
Name of this pool. Mainly for debugging. Used to name worker threads.
U32 mNumPendingItems
Number of work items that have not yet completed execution.
U32 mNumThreads
Number of worker threads spawned by the pool.
U32 mNumThreadsAwake
Number of worker threads in non-sleeping state.
U32 mNumThreadsReady
Number of worker threads guaranteed to be non-blocking.
Semaphore mSemaphore
Semaphore used to wake up threads, if necessary.
WorkerThread * mThreads
List of worker threads.
QueueType mWorkItemQueue
Threaded priority queue for concurrent access by worker threads.
Protected Static Attributes
bool smForceAllMainThread
Force all work items to execute on main thread; turns this into a single-threaded system.
Primarily useful to find whether malfunctions are caused by parallel execution or not.
QueueType smMainThreadQueue
Work queue for main thread; can be used to ping back work items to main thread that need processing that can only happen on main thread.
U32 smMainThreadTimeMS
Public Functions
ThreadPool(const char * name, U32 numThreads)
Create a new thread pool with the given number of worker threads.
If numThreads is zero (the default), the number of threads created will be based on the number of CPU cores available.
Parameters:
numThreads | Number of threads to create or zero for default. |
~ThreadPool()
flushWorkItems(S32 timeOut)
For the global pool, it is very important to only ever call this function on the main thread and to let work items only ever come from the main thread.
Otherwise this function has the potential of dead-locking as new work items may constantly be fed to the queue without it ever getting empty.
Parameters:
timeOut | Soft limit on the number of milliseconds to wait for the queue to flush out. -1 = infinite. |
getQueueTimeBasedPriorityBoost()
Return the priority increment applied to work items on each passing of the update interval.
getQueueUpdateInterval()
Return the interval in which item priorities are updated on the queue.
update interval in milliseconds.
queueWorkItem(WorkItem * item)
setQueueTimeBasedPriorityBoost(F32 value)
Set the priority increment applied to work items on each update interval.
Parameters:
value | Priority increment. Set to zero to deactivate. |
setQueueUpdateInterval(U32 milliSeconds)
Set the update interval of the work item queue to the given value.
Parameters:
milliSeconds | Time between updates in milliseconds. |
shutdown()
Manually shutdown threads outside of static destructors.
waitForAllItems(S32 timeOut)
If you're using a non-global thread pool to parallelise some work, you may want to block until all the parallel work is complete.
As with flushWorkItems, this method may block indefinitely if new items keep getting added to the pool before old ones finish.
This method will not wait for items queued on the main thread using queueWorkItemOnMainThread!
Parameters:
timeOut | Soft limit on the number of milliseconds to wait for all items to complete. -1 = infinite. |
Public Static Functions
getForceAllMainThread()
getMainThreadThresholdTimeMS()
GLOBAL()
Return the global thread pool singleton.
processMainThreadWorkItems()
Process work items waiting on the main thread's work queue.
There is a soft limit imposed on the time this method is allowed to run so as to balance frame-to-frame load. However, work items, once their processing is initiated, will not be suspended and will run for as long as they take to complete, so make sure individual items perform as little work as necessary.
ThreadPool::getMainThreadThesholdTimeMS
queueWorkItemOnMainThread(WorkItem * item)
Add a work item to the main thread's work queue.
The main thread's work queue will be processed each frame using a set timeout to limit the work being done. Nonetheless, work items will not be suspended in-midst of processing, so make sure that whatever work you issue to the main thread is light work or you may see short hangs in gameplay.
To reiterate this: any code executed through this interface directly adds to frame processing time on the main thread.
This method may (and is meant to) be called from threads other than the main thread.