ThreadPool

Engine/source/platform/threads/threadPool.h

Asynchronous work manager.

More...

Classes:

class

A ThreadPool context defines a logical context in which WorkItems are being executed.

class

An action to execute on a worker thread from the pool.

class

Value wrapper for work items while placed on priority queue.

Public Types

WorkItemPtr 

Public Friends

struct

Protected Attributes

Name of this pool. Mainly for debugging. Used to name worker threads.

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.

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.

Set the priority increment applied to work items on each update interval.

Set the update interval of the work item queue to the given value.

Manually shutdown threads outside of static destructors.

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

Return the global thread pool singleton.

Process work items waiting on the main thread's work queue.

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:

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.

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 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.

return:

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.

see:

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.