HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_TaskExclusive< T > Class Template Reference

#include <UT_TaskExclusive.h>

Public Member Functions

 UT_TaskExclusive ()
 
void execute (T &func, bool run_in_task_arena=true, bool use_spinlock=false)
 
void executeNoThread (T &func)
 
void reset ()
 
bool hasRun () const
 

Detailed Description

template<class T>
class UT_TaskExclusive< T >

This is a lock-free implementation for exclusive task execution. That is, a task which needs to be performed once (i.e. std::once). However, this construct will allow TBB to recycle blocked tasks so they can be used for other processing.

This can be used as an alternate to a lock. If code underneath a lock calls into TBB, this can lead to a deadlock since TBB can steal a child task to complete a parent task outside the lock. This typically requires a separate task arena. A lock will also block a thread, preventing it from participating in other tasks.

UT_TaskExclusive provides a good alternative, ensuring that only one thread will execute the functor, and all other threads which wait for the functor to finish will be allowed to participate in other computation (even to help computing parallel tasks in the functor).

The class is templated on a functor which is used to actually perform the execution. The template functor needs to have a operator()() method.

For example, given a single Object which has a deferredInitialize() method that may get called from multiple threads:

class Object
{
public:
// Users call deferredInitialize when they want the object to be
// initialized. However, it's possible the object may need to be
// initialized by multiple threads. The object uses UT_TaskExclusive
// to ensure doInitialization() is only executed one time.
void deferredInitialize()
{
myExclusive.execute(*this);
}
void operator()()
{
// This method will only be called once, even if
// multiple threads invoke the deferredInitialize() method
// simultaneously.
doInitialization();
}
}

If you have multiple methods that should only be called one time, you can always create a nested object functor.

If the functor is likely to create further tbb tasks, you can ensure these tasks are run in their own task arena by setting run_in_task_arena to true (the default).

Definition at line 74 of file UT_TaskExclusive.h.

Constructor & Destructor Documentation

template<class T>
UT_TaskExclusive< T >::UT_TaskExclusive ( )
inline

Definition at line 77 of file UT_TaskExclusive.h.

Member Function Documentation

template<class T>
void UT_TaskExclusive< T >::execute ( T func,
bool  run_in_task_arena = true,
bool  use_spinlock = false 
)
inline

Execute the compute task. This will guarantee the function has been run before the execute() function returns. However, no locking will be done.

If multiple threads try to call the function simultaneously, only one function will run, while the other will yield its cycles to other parallel tasks. When the first task completes, both threads will return.

If the functor is likely to create further tbb tasks, you can ensure these tasks are run in their own task arena by setting run_in_task_arena to true (the default). The primary reason for having a separate task arena is that the if the functor creates further tasks, and one of these tasks is also dependent on the task exclusive, this can lead to a tbb deadlock (a tbb stack lock).

Definition at line 97 of file UT_TaskExclusive.h.

template<class T>
void UT_TaskExclusive< T >::executeNoThread ( T func)
inline

Executes the compute task in this thread without any locking or protection. Useful if the caller has already setup the appropriate lock.

Definition at line 234 of file UT_TaskExclusive.h.

template<class T>
bool UT_TaskExclusive< T >::hasRun ( ) const
inline

Test whether the function has been executed. This is thread-safe, but doesn't count on other threads which may be in the process of running it.

Definition at line 251 of file UT_TaskExclusive.h.

template<class T>
void UT_TaskExclusive< T >::reset ( void  )
inline

Resetting the exclusive task should only be done when there's no possibility that any threads are trying to execute or relying on the results of the computation.

Definition at line 246 of file UT_TaskExclusive.h.


The documentation for this class was generated from the following file: