task_arena Class

Summary

Explicit, user-managed task scheduler arena representation.

Syntax

class task_arena;

Header

#define TBB_PREVIEW_TASK_ARENA 1
#include “tbb/task_arena.h”

Description

A task_arena class represents an internal task scheduler object where a number of threads, limited by a maximal concurrency level, share and execute tasks.

The concurrency level of a task_arena is isolated and not affected by previous task_scheduler_init specifications.

Note

The total number of threads created for a process is limited by whichever is largest: the default number of threads for the machine or the value specified by the first task_scheduler_init object. Therefore the number of threads assigned to a task_arena will never exceed that maximum value, regardless of the concurrency level.

Note

A task_arena may get fewer workers and never get the specified number of threads, even if the specified concurrency level is lower than the allowed maximum.

A task_arena object keeps a reference to its internal representation, but does not fully control its lifetime. It cannot be destroyed until it contains tasks and/or other worker threads reference it.

Note

The task_arena constructors do not create the internal arena objects. They are created lazily on first use, or by explicit call to task_arena::initialize.

Each user thread that explicitly or implicitly creates a task_scheduler_init object contains an implicit internal task arena object. The tasks spawned or enqueued in an arena cannot be executed in a different arena.

This preview feature requires linkage with the Community Preview library.

Caution

If linking with Community Preview library, always define TBB_PREVIEW_TASK_ARENA. Some other features like task_scheduler_observer can depend on this definition.

Members

namespace tbb {
class task_arena {
public:
    static const int automatic = implementation-defined;
    static int current_slot();
    task_arena(int max_concurrency = automatic, unsigned reserved_for_masters = 1);
    task_arena(const task_arena &s);
    ~task_arena();
    void initialize();
    void initialize(int max_concurrency, unsigned reserved_for_masters = 1);
    void terminate();
    bool is_active();
    template<typename F> void enqueue( const F& f );
    template<typename F> void enqueue( const F& f, priority_t p );
    template<typename F> void execute(F& f);
    template<typename F> void execute(const F& f);
    void wait_until_empty();
};
}

Examples

The following example runs two paralel_for loops concurrently; one that is scalable and one that is not. The non-scalable loop is limited to at most 2 threads so that the majority of the threads can be saved for the more scalable loop.

tbb::task_scheduler_init def_init; // Use the default number of threads
tbb::task_arena limited(2);// no more than 2 threads in this arena

limited.enqueue([]{ // use at most 2 threads
    tbb::parallel_for(1, N, unscalable_work());
}); 

// Run another job concurrently with the loop above
// It can use the default number of threads:
tbb::parallel_for(1, M, scalable_work());

limited.wait_until_empty(); // ensure async work is finished

The last line of the above example calls wait_until_empty() to wait for all work in the arena to be completed. If you need to wait for a specific subset of tasks to complete, a task_group can be used as shown below:

tbb::task_arena arena;
tbb::task_group tg;

// Enqueue some job(s) in a task group 
for( int i=0; i<N; ++i)
    arena.enqueue([&,=i] { tg.run( F(i) ) });

// Do some other work ...

// Put the wait for the task group inside execute()
// This will wait only for the tasks that are in
// this arena.
arena.execute([&]{ tg.wait(); }); 

The following table provides additional information on the members of this template class.

Member Description
task_arena(int max_concurrency = automatic, unsigned reserved_for_masters = 1)

Creates a task_arena with certain concurrency limit and some portion of it reserved for application threads.

Note

For the community preview implementation of task_arena, the only valid values for reserved_for_masters are 0 and 1.

static const int automatic

When passed as max_concurrency to the above constructor, arena concurrency will be automatically set based on the hardware configuration.

task_arena(const task_arena&)

Copies settings from another task_arena instance.

~task_arena()

Removes the reference to the internal arena representation, and destroys the task_arena() instance. Not thread safe w.r.t. concurrent invocations of other methods.

void initialize();

void initialize(int max_concurrency, unsigned reserved_for_masters = 1);

Performs actual initialization of internal arena representation. If arguments are specified, overrides previous concurrency settings. Has no effect when called on already initialized arena.

Note

After the call to initialize, the arena concurrency is fixed and cannot be changed.
void terminate() Removes the reference to the internal arena representation without destroying the task_arena object, which can then be re-used. Not thread safe w.r.t. concurrent invocations of other methods.
bool is_active() Returns true if the arena has been initialized, false otherwise.
template<F> void enqueue(const F&)

Enqueues a task into the arena to process specified functor and immediately returns.

Note

Does not require the calling thread to join the arena; i.e. any number of threads outside of the arena can submit work to the arena without blocking.

Caution

There is no guarantee that tasks enqueued in an arena execute concurrently with respect to any other arena’s tasks.
template<F> void enqueue(const F&, priority_t)

Enqueues a task with specified task priority. Is similar to enqueue( const F& ) in all other ways.

template<F> void execute(F&)

template<F> void execute(const F&)

If possible, the calling thread joins the arena and executes the specified functor, then leaves the arena and returns to previous task scheduler state.

If not possible to join, the call wraps the functor into a task, enqueues it in the arena and waits on an OS kernel synchronization object for task completion.

Note

Any number of threads outside of the arena can submit work to the arena and be blocked. However, only the maximal number of threads specified for the arena can participate in executing tasks.

Note

May decrement the arena's demand for worker threads, causing a worker to leave, and thereby freeing a slot for the calling thread.
void wait_until_empty()

Wait for all work in the arena to be completed. The calling thread joins the arena if possible, in the same way as execute().

Caution

This method waits for all work in the arena, even work submitted by other application threads.
static int current_slot()

Returns: The index of the slot that the calling thread is assigned to in its current arena. This can be used, for example, by a task_scheduler_observer to pin threads entering an arena to specific hardware.

For more complete information about compiler optimizations, see our Optimization Notice.