task_group.h
Go to the documentation of this file.
/*
Copyright (c) 2005-2020 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __TBB_task_group_H
#define __TBB_task_group_H
#define __TBB_task_group_H_include_area
#include "internal/_warning_suppress_enable_notice.h"
#include "task.h"
#include "tbb_exception.h"
#include "internal/_template_helpers.h"
#if TBB_PREVIEW_ISOLATED_TASK_GROUP && __TBB_TASK_ISOLATION
#include "task_arena.h"
#endif
#if __TBB_TASK_GROUP_CONTEXT
namespace tbb {
namespace internal {
template<typename F> class task_handle_task;
}
class task_group;
class structured_task_group;
#if TBB_PREVIEW_ISOLATED_TASK_GROUP && __TBB_TASK_ISOLATION
class isolated_task_group;
#endif
template<typename F>
class task_handle : internal::no_assign {
template<typename _F> friend class internal::task_handle_task;
friend class task_group;
friend class structured_task_group;
#if TBB_PREVIEW_ISOLATED_TASK_GROUP && __TBB_TASK_ISOLATION
friend class isolated_task_group;
#endif
static const intptr_t scheduled = 0x1;
F my_func;
intptr_t my_state;
void mark_scheduled () {
// The check here is intentionally lax to avoid the impact of interlocked operation
if ( my_state & scheduled )
internal::throw_exception( internal::eid_invalid_multiple_scheduling );
my_state |= scheduled;
}
public:
task_handle( const F& f ) : my_func(f), my_state(0) {}
#if __TBB_CPP11_RVALUE_REF_PRESENT
task_handle( F&& f ) : my_func( std::move(f)), my_state(0) {}
#endif
void operator() () const { my_func(); }
};
enum task_group_status {
not_complete,
complete,
canceled
};
namespace internal {
template<typename F>
class task_handle_task : public task {
task_handle<F>& my_handle;
task* execute() __TBB_override {
my_handle();
return NULL;
}
public:
task_handle_task( task_handle<F>& h ) : my_handle(h) { h.mark_scheduled(); }
};
class task_group_base : internal::no_copy {
class ref_count_guard : internal::no_copy {
task& my_task;
public:
ref_count_guard(task& t) : my_task(t) {
my_task.increment_ref_count();
}
~ref_count_guard() {
my_task.decrement_ref_count();
}
};
protected:
empty_task* my_root;
task_group_context my_context;
template<typename F>
task_group_status internal_run_and_wait( F& f ) {
__TBB_TRY {
if ( !my_context.is_group_execution_cancelled() ) {
// We need to increase the reference count of the root task to notify waiters that
// this task group has some work in progress.
ref_count_guard guard(*my_root);
f();
}
} __TBB_CATCH( ... ) {
my_context.register_pending_exception();
}
return wait();
}
template<typename Task, typename F>
task* prepare_task( __TBB_FORWARDING_REF(F) f ) {
return new( task::allocate_additional_child_of(*my_root) ) Task( internal::forward<F>(f) );
}
public:
task_group_base( uintptr_t traits = 0 )
: my_context(task_group_context::bound, task_group_context::default_traits | traits)
{
my_root = new( task::allocate_root(my_context) ) empty_task;
my_root->set_ref_count(1);
}
~task_group_base() __TBB_NOEXCEPT(false) {
if( my_root->ref_count() > 1 ) {
#if __TBB_CPP17_UNCAUGHT_EXCEPTIONS_PRESENT
bool stack_unwinding_in_progress = std::uncaught_exceptions() > 0;
#else
bool stack_unwinding_in_progress = std::uncaught_exception();
#endif
// Always attempt to do proper cleanup to avoid inevitable memory corruption
// in case of missing wait (for the sake of better testability & debuggability)
if ( !is_canceling() )
cancel();
__TBB_TRY {
my_root->wait_for_all();
} __TBB_CATCH (...) {
task::destroy(*my_root);
__TBB_RETHROW();
}
task::destroy(*my_root);
if ( !stack_unwinding_in_progress )
internal::throw_exception( internal::eid_missing_wait );
}
else {
task::destroy(*my_root);
}
}
template<typename F>
void run( task_handle<F>& h ) {
task::spawn( *prepare_task< internal::task_handle_task<F> >(h) );
}
task_group_status wait() {
__TBB_TRY {
my_root->wait_for_all();
} __TBB_CATCH( ... ) {
my_context.reset();
__TBB_RETHROW();
}
if ( my_context.is_group_execution_cancelled() ) {
// TODO: the reset method is not thread-safe. Ensure the correct behavior.
my_context.reset();
return canceled;
}
return complete;
}
bool is_canceling() {
return my_context.is_group_execution_cancelled();
}
void cancel() {
my_context.cancel_group_execution();
}
}; // class task_group_base
} // namespace internal
class task_group : public internal::task_group_base {
public:
task_group () : task_group_base( task_group_context::concurrent_wait ) {}
#if __SUNPRO_CC
template<typename F>
void run( task_handle<F>& h ) {
internal_run< internal::task_handle_task<F> >( h );
}
#else
using task_group_base::run;
#endif
#if __TBB_CPP11_RVALUE_REF_PRESENT
template<typename F>
void run( F&& f ) {
task::spawn( *prepare_task< internal::function_task< typename internal::strip<F>::type > >(std::forward<F>(f)) );
}
#else
template<typename F>
void run(const F& f) {
task::spawn( *prepare_task< internal::function_task<F> >(f) );
}
#endif
template<typename F>
task_group_status run_and_wait( const F& f ) {
return internal_run_and_wait<const F>( f );
}
// TODO: add task_handle rvalues support
template<typename F>
task_group_status run_and_wait( task_handle<F>& h ) {
h.mark_scheduled();
return internal_run_and_wait< task_handle<F> >( h );
}
}; // class task_group
class __TBB_DEPRECATED structured_task_group : public internal::task_group_base {
public:
// TODO: add task_handle rvalues support
template<typename F>
task_group_status run_and_wait ( task_handle<F>& h ) {
h.mark_scheduled();
return internal_run_and_wait< task_handle<F> >( h );
}
task_group_status wait() {
task_group_status res = task_group_base::wait();
my_root->set_ref_count(1);
return res;
}
}; // class structured_task_group
#if TBB_PREVIEW_ISOLATED_TASK_GROUP && __TBB_TASK_ISOLATION
namespace internal {
using interface7::internal::delegate_base;
using interface7::internal::isolate_within_arena;
class spawn_delegate : public delegate_base {
task* task_to_spawn;
void operator()() const __TBB_override {
task::spawn(*task_to_spawn);
}
public:
spawn_delegate(task* a_task) : task_to_spawn(a_task) {}
};
class wait_delegate : public delegate_base {
void operator()() const __TBB_override {
status = tg.wait();
}
protected:
task_group& tg;
task_group_status& status;
public:
wait_delegate(task_group& a_group, task_group_status& tgs)
: tg(a_group), status(tgs) {}
};
template<typename F>
class run_wait_delegate : public wait_delegate {
F& func;
void operator()() const __TBB_override {
status = tg.run_and_wait( func );
}
public:
run_wait_delegate(task_group& a_group, F& a_func, task_group_status& tgs)
: wait_delegate(a_group, tgs), func(a_func) {}
};
} // namespace internal
class isolated_task_group : public task_group {
intptr_t this_isolation() {
return reinterpret_cast<intptr_t>(this);
}
public:
isolated_task_group () : task_group() {}
#if __TBB_CPP11_RVALUE_REF_PRESENT
template<typename F>
void run( F&& f ) {
internal::spawn_delegate sd(
prepare_task< internal::function_task< typename internal::strip<F>::type > >(std::forward<F>(f))
);
internal::isolate_within_arena( sd, this_isolation() );
}
#else
template<typename F>
void run(const F& f) {
internal::spawn_delegate sd( prepare_task< internal::function_task<F> >(f) );
internal::isolate_within_arena( sd, this_isolation() );
}
#endif
template<typename F>
task_group_status run_and_wait( const F& f ) {
task_group_status result = not_complete;
internal::run_wait_delegate< const F > rwd( *this, f, result );
internal::isolate_within_arena( rwd, this_isolation() );
__TBB_ASSERT( result!=not_complete, "premature exit from wait?" );
return result;
}
// TODO: add task_handle rvalues support
template<typename F>
void run( task_handle<F>& h ) {
internal::spawn_delegate sd( prepare_task< internal::task_handle_task<F> >(h) );
internal::isolate_within_arena( sd, this_isolation() );
}
template<typename F>
task_group_status run_and_wait ( task_handle<F>& h ) {
task_group_status result = not_complete;
internal::run_wait_delegate< task_handle<F> > rwd( *this, h, result );
internal::isolate_within_arena( rwd, this_isolation() );
__TBB_ASSERT( result!=not_complete, "premature exit from wait?" );
return result;
}
task_group_status wait() {
task_group_status result = not_complete;
internal::wait_delegate wd( *this, result );
internal::isolate_within_arena( wd, this_isolation() );
__TBB_ASSERT( result!=not_complete, "premature exit from wait?" );
return result;
}
}; // class isolated_task_group
#endif // TBB_PREVIEW_ISOLATED_TASK_GROUP && __TBB_TASK_ISOLATION
inline
bool is_current_task_group_canceling() {
return task::self().is_cancelled();
}
#if __TBB_CPP11_RVALUE_REF_PRESENT
template<class F>
task_handle< typename internal::strip<F>::type > make_task( F&& f ) {
return task_handle< typename internal::strip<F>::type >( std::forward<F>(f) );
}
#else
template<class F>
task_handle<F> make_task( const F& f ) {
return task_handle<F>( f );
}
#endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
} // namespace tbb
#endif /* __TBB_TASK_GROUP_CONTEXT */
#include "internal/_warning_suppress_disable_notice.h"
#undef __TBB_task_group_H_include_area
#endif /* __TBB_task_group_H */
_template_helpers.h
_warning_suppress_disable_notice.h
_warning_suppress_enable_notice.h
task.h
task_arena.h
__TBB_DEPRECATED
#define __TBB_DEPRECATED
Definition: tbb_config.h:637
tbb_exception.h
__TBB_CATCH
#define __TBB_CATCH(e)
Definition: tbb_stddef.h:284
__TBB_NOEXCEPT
#define __TBB_NOEXCEPT(expression)
Definition: tbb_stddef.h:110
__TBB_TRY
#define __TBB_TRY
Definition: tbb_stddef.h:283
__TBB_ASSERT
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
__TBB_override
#define __TBB_override
Definition: tbb_stddef.h:240
__TBB_FORWARDING_REF
#define __TBB_FORWARDING_REF(A)
Definition: tbb_stddef.h:517
__TBB_RETHROW
#define __TBB_RETHROW()
Definition: tbb_stddef.h:286
task
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task * task
Definition: ittnotify_static.h:119
h
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function h
Definition: ittnotify_static.h:159
tbb
The graph class.
Definition: serial/tbb/parallel_for.h:46
tbb::task_group_status
task_group_status
Definition: task_group.h:73
tbb::complete
@ complete
Definition: task_group.h:75
tbb::canceled
@ canceled
Definition: task_group.h:76
tbb::not_complete
@ not_complete
Definition: task_group.h:74
tbb::is_current_task_group_canceling
bool is_current_task_group_canceling()
Definition: task_group.h:343
tbb::move
void move(tbb_thread &t1, tbb_thread &t2)
Definition: tbb_thread.h:319
tbb::make_task
task_handle< typename internal::strip< F >::type > make_task(F &&f)
Definition: task_group.h:349
tbb::internal::throw_exception
void throw_exception(exception_id eid)
Versionless convenience wrapper for throw_exception_v4()
Definition: tbb_exception.h:105
tbb::internal::eid_missing_wait
@ eid_missing_wait
Definition: tbb_exception.h:74
tbb::internal::eid_invalid_multiple_scheduling
@ eid_invalid_multiple_scheduling
Definition: tbb_exception.h:75
internal
Definition: _flow_graph_async_msg_impl.h:24
tbb::interface7::internal::isolate_within_arena
void __TBB_EXPORTED_FUNC isolate_within_arena(delegate_base &d, intptr_t isolation=0)
tbb::internal::strip::type
T type
Definition: _template_helpers.h:38
tbb::task_group_context
Used to form groups of tasks.
Definition: task.h:358
tbb::task_group_context::cancel_group_execution
bool __TBB_EXPORTED_METHOD cancel_group_execution()
Initiates cancellation of all tasks in this cancellation group and its subordinate groups.
tbb::task_group_context::is_group_execution_cancelled
bool __TBB_EXPORTED_METHOD is_group_execution_cancelled() const
Returns true if the context received cancellation request.
tbb::task_group_context::register_pending_exception
void __TBB_EXPORTED_METHOD register_pending_exception()
Records the pending exception, and cancels the task group.
tbb::task_group_context::reset
void __TBB_EXPORTED_METHOD reset()
Forcefully reinitializes the context after the task tree it was associated with is completed.
tbb::task
Base class for user-defined tasks.
Definition: task.h:615
tbb::task::decrement_ref_count
int decrement_ref_count()
Atomically decrement reference count and returns its new value.
Definition: task.h:788
tbb::task::is_cancelled
bool is_cancelled() const
Returns true if the context has received cancellation request.
Definition: task.h:974
tbb::task::ref_count
int ref_count() const
The internal reference count.
Definition: task.h:915
tbb::task::self
static task &__TBB_EXPORTED_FUNC self()
The innermost task being executed or destroyed by the current thread at the moment.
Definition: task.cpp:201
tbb::task::wait_for_all
void wait_for_all()
Wait for reference count to become one, and set reference count to zero.
Definition: task.h:819
tbb::task::allocate_root
static internal::allocate_root_proxy allocate_root()
Returns proxy for overloaded new that allocates a root task.
Definition: task.h:663
tbb::task::set_ref_count
void set_ref_count(int count)
Set reference count.
Definition: task.h:761
tbb::task::increment_ref_count
void increment_ref_count()
Atomically increment reference count.
Definition: task.h:771
tbb::empty_task
task that does nothing. Useful for synchronization.
Definition: task.h:1042
tbb::internal::function_task
Definition: task.h:1051
tbb::internal::task_handle_task
Definition: task_group.h:82
tbb::internal::task_handle_task::execute
task * execute() __TBB_override
Should be overridden by derived classes.
Definition: task_group.h:84
tbb::internal::task_handle_task::my_handle
task_handle< F > & my_handle
Definition: task_group.h:83
tbb::internal::task_handle_task::task_handle_task
task_handle_task(task_handle< F > &h)
Definition: task_group.h:89
tbb::task_handle
Definition: task_group.h:45
tbb::task_handle::task_handle
task_handle(const F &f)
Definition: task_group.h:65
tbb::task_handle::mark_scheduled
void mark_scheduled()
Definition: task_group.h:58
tbb::task_handle::operator()
void operator()() const
Definition: task_group.h:70
tbb::task_handle::task_handle
task_handle(F &&f)
Definition: task_group.h:67
tbb::task_handle::my_func
F my_func
Definition: task_group.h:55
tbb::task_handle::my_state
intptr_t my_state
Definition: task_group.h:56
tbb::task_handle::scheduled
static const intptr_t scheduled
Definition: task_group.h:53
tbb::internal::task_group_base
Definition: task_group.h:92
tbb::internal::task_group_base::cancel
void cancel()
Definition: task_group.h:185
tbb::internal::task_group_base::my_root
empty_task * my_root
Definition: task_group.h:104
tbb::internal::task_group_base::~task_group_base
~task_group_base() __TBB_NOEXCEPT(false)
Definition: task_group.h:135
tbb::internal::task_group_base::prepare_task
task * prepare_task(__TBB_FORWARDING_REF(F) f)
Definition: task_group.h:123
tbb::internal::task_group_base::run
void run(task_handle< F > &h)
Definition: task_group.h:162
tbb::internal::task_group_base::is_canceling
bool is_canceling()
Definition: task_group.h:181
tbb::internal::task_group_base::wait
task_group_status wait()
Definition: task_group.h:166
tbb::internal::task_group_base::task_group_base
task_group_base(uintptr_t traits=0)
Definition: task_group.h:128
tbb::internal::task_group_base::internal_run_and_wait
task_group_status internal_run_and_wait(F &f)
Definition: task_group.h:108
tbb::internal::task_group_base::my_context
task_group_context my_context
Definition: task_group.h:105
tbb::internal::task_group_base::ref_count_guard
Definition: task_group.h:93
tbb::internal::task_group_base::ref_count_guard::~ref_count_guard
~ref_count_guard()
Definition: task_group.h:99
tbb::internal::task_group_base::ref_count_guard::ref_count_guard
ref_count_guard(task &t)
Definition: task_group.h:96
tbb::internal::task_group_base::ref_count_guard::my_task
task & my_task
Definition: task_group.h:94
tbb::task_group
Definition: task_group.h:192
tbb::task_group::run
void run(F &&f)
Definition: task_group.h:207
tbb::task_group::run_and_wait
task_group_status run_and_wait(task_handle< F > &h)
Definition: task_group.h:224
tbb::task_group::task_group
task_group()
Definition: task_group.h:194
tbb::task_group::run_and_wait
task_group_status run_and_wait(const F &f)
Definition: task_group.h:218
tbb::structured_task_group
Definition: task_group.h:230
tbb::structured_task_group::wait
task_group_status wait()
Definition: task_group.h:239
tbb::structured_task_group::run_and_wait
task_group_status run_and_wait(task_handle< F > &h)
Definition: task_group.h:234
tbb::internal::no_assign
Base class for types that should not be assigned.
Definition: tbb_stddef.h:322
tbb::internal::no_copy
Base class for types that should not be copied or assigned.
Definition: tbb_stddef.h:330

Copyright © 2005-2020 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.