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

Parent topic: Community Preview Features

- task_scheduler_observer Class extensions

## See Also

task_scheduler_observer Class extensions
Task Groups
task_scheduler_init Class