Intel(R) Threading Building Blocks Doxygen Documentation  version 4.2.3
task_group.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2005-2019 Intel Corporation
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 #ifndef __TBB_task_group_H
18 #define __TBB_task_group_H
19 
20 #include "task.h"
21 #include "tbb_exception.h"
23 
24 #if __TBB_TASK_GROUP_CONTEXT
25 
26 namespace tbb {
27 
28 namespace internal {
29  template<typename F> class task_handle_task;
30 }
31 
32 class task_group;
34 
35 template<typename F>
36 class task_handle : internal::no_assign {
37  template<typename _F> friend class internal::task_handle_task;
38  friend class task_group;
39  friend class structured_task_group;
40 
41  static const intptr_t scheduled = 0x1;
42 
44  intptr_t my_state;
45 
46  void mark_scheduled () {
47  // The check here is intentionally lax to avoid the impact of interlocked operation
48  if ( my_state & scheduled )
50  my_state |= scheduled;
51  }
52 public:
53  task_handle( const F& f ) : my_func(f), my_state(0) {}
54 #if __TBB_CPP11_RVALUE_REF_PRESENT
55  task_handle( F&& f ) : my_func( std::move(f)), my_state(0) {}
56 #endif
57 
58  void operator() () const { my_func(); }
59 };
60 
65 };
66 
67 namespace internal {
68 
69 template<typename F>
70 class task_handle_task : public task {
73  my_handle();
74  return NULL;
75  }
76 public:
77  task_handle_task( task_handle<F>& h ) : my_handle(h) { h.mark_scheduled(); }
78 };
79 
80 class task_group_base : internal::no_copy {
81  class ref_count_guard : internal::no_copy {
83  public:
84  ref_count_guard(task& t) : my_task(t) {
85  my_task.increment_ref_count();
86  }
88  my_task.decrement_ref_count();
89  }
90  };
91 protected:
94 
95  task& owner () { return *my_root; }
96 
97  template<typename F>
99  __TBB_TRY {
100  if ( !my_context.is_group_execution_cancelled() ) {
101  // We need to increase the reference count of the root task to notify waiters that
102  // this task group has some work in progress.
103  ref_count_guard guard(*my_root);
104  f();
105  }
106  } __TBB_CATCH( ... ) {
107  my_context.register_pending_exception();
108  }
109  return wait();
110  }
111 
112  template<typename Task, typename F>
114  owner().spawn( *new( owner().allocate_additional_child_of(*my_root) ) Task( internal::forward<F>(f) ));
115  }
116 
117 public:
118  task_group_base( uintptr_t traits = 0 )
119  : my_context(task_group_context::bound, task_group_context::default_traits | traits)
120  {
121  my_root = new( task::allocate_root(my_context) ) empty_task;
122  my_root->set_ref_count(1);
123  }
124 
126  if( my_root->ref_count() > 1 ) {
127 #if __TBB_CPP17_UNCAUGHT_EXCEPTIONS_PRESENT
128  bool stack_unwinding_in_progress = std::uncaught_exceptions() > 0;
129 #else
130  bool stack_unwinding_in_progress = std::uncaught_exception();
131 #endif
132  // Always attempt to do proper cleanup to avoid inevitable memory corruption
133  // in case of missing wait (for the sake of better testability & debuggability)
134  if ( !is_canceling() )
135  cancel();
136  __TBB_TRY {
137  my_root->wait_for_all();
138  } __TBB_CATCH (...) {
139  task::destroy(*my_root);
140  __TBB_RETHROW();
141  }
142  task::destroy(*my_root);
143  if ( !stack_unwinding_in_progress )
145  }
146  else {
147  task::destroy(*my_root);
148  }
149  }
150 
151  template<typename F>
152  void run( task_handle<F>& h ) {
153  internal_run< internal::task_handle_task<F> >( h );
154  }
155 
157  __TBB_TRY {
158  my_root->wait_for_all();
159  } __TBB_CATCH( ... ) {
160  my_context.reset();
161  __TBB_RETHROW();
162  }
163  if ( my_context.is_group_execution_cancelled() ) {
164  // TODO: the reset method is not thread-safe. Ensure the correct behavior.
165  my_context.reset();
166  return canceled;
167  }
168  return complete;
169  }
170 
171  bool is_canceling() {
172  return my_context.is_group_execution_cancelled();
173  }
174 
175  void cancel() {
176  my_context.cancel_group_execution();
177  }
178 }; // class task_group_base
179 
180 } // namespace internal
181 
182 class task_group : public internal::task_group_base {
183 public:
184  task_group () : task_group_base( task_group_context::concurrent_wait ) {}
185 
186 #if __SUNPRO_CC
187  template<typename F>
188  void run( task_handle<F>& h ) {
189  internal_run< internal::task_handle_task<F> >( h );
190  }
191 #else
192  using task_group_base::run;
193 #endif
194 
195 #if __TBB_CPP11_RVALUE_REF_PRESENT
196  template<typename F>
197  void run( F&& f ) {
199  }
200 #else
201  template<typename F>
202  void run(const F& f) {
203  internal_run<internal::function_task<F> >(f);
204  }
205 #endif
206 
207  template<typename F>
209  return internal_run_and_wait<const F>( f );
210  }
211 
212  // TODO: add task_handle rvalues support
213  template<typename F>
215  h.mark_scheduled();
216  return internal_run_and_wait< task_handle<F> >( h );
217  }
218 }; // class task_group
219 
220 class structured_task_group : public internal::task_group_base {
221 public:
222  // TODO: add task_handle rvalues support
223  template<typename F>
225  h.mark_scheduled();
226  return internal_run_and_wait< task_handle<F> >( h );
227  }
228 
231  my_root->set_ref_count(1);
232  return res;
233  }
234 }; // class structured_task_group
235 
236 inline
238  return task::self().is_cancelled();
239 }
240 
241 #if __TBB_CPP11_RVALUE_REF_PRESENT
242 template<class F>
244  return task_handle< typename internal::strip<F>::type >( std::forward<F>(f) );
245 }
246 #else
247 template<class F>
248 task_handle<F> make_task( const F& f ) {
249  return task_handle<F>( f );
250 }
251 #endif /* __TBB_CPP11_RVALUE_REF_PRESENT */
252 
253 } // namespace tbb
254 
255 #endif /* __TBB_TASK_GROUP_CONTEXT */
256 
257 #endif /* __TBB_task_group_H */
task_group_status run_and_wait(task_handle< F > &h)
Definition: task_group.h:214
void set_ref_count(int count)
Set reference count.
Definition: task.h:731
#define __TBB_override
Definition: tbb_stddef.h:240
task_handle< typename internal::strip< F >::type > make_task(F &&f)
Definition: task_group.h:243
task_handle(const F &f)
Definition: task_group.h:53
~task_group_base() __TBB_NOEXCEPT(false)
Definition: task_group.h:125
void run(F &&f)
Definition: task_group.h:197
void __TBB_EXPORTED_METHOD register_pending_exception()
Records the pending exception, and cancels the task group.
static internal::allocate_root_proxy allocate_root()
Returns proxy for overloaded new that allocates a root task.
Definition: task.h:633
void __TBB_EXPORTED_METHOD reset()
Forcefully reinitializes the context after the task tree it was associated with is completed...
task_group_context my_context
Definition: task_group.h:93
void mark_scheduled()
Definition: task_group.h:46
The graph class.
task_handle< F > & my_handle
Definition: task_group.h:71
task * execute() __TBB_override
Should be overridden by derived classes.
Definition: task_group.h:72
task_group_status run_and_wait(const F &f)
Definition: task_group.h:208
bool __TBB_EXPORTED_METHOD cancel_group_execution()
Initiates cancellation of all tasks in this cancellation group and its subordinate groups...
void run(task_handle< F > &h)
Definition: task_group.h:152
int decrement_ref_count()
Atomically decrement reference count and returns its new value.
Definition: task.h:758
task_group_base(uintptr_t traits=0)
Definition: task_group.h:118
bool is_cancelled() const
Returns true if the context has received cancellation request.
Definition: task.h:918
#define __TBB_NOEXCEPT(expression)
Definition: tbb_stddef.h:110
task_group_status run_and_wait(task_handle< F > &h)
Definition: task_group.h:224
task_group_status wait()
Definition: task_group.h:156
static task &__TBB_EXPORTED_FUNC self()
The innermost task being executed or destroyed by the current thread at the moment.
Definition: task.cpp:201
void move(tbb_thread &t1, tbb_thread &t2)
Definition: tbb_thread.h:305
task_group_status internal_run_and_wait(F &f)
Definition: task_group.h:98
task that does nothing. Useful for synchronization.
Definition: task.h:964
#define __TBB_FORWARDING_REF(A)
Definition: tbb_stddef.h:496
Used to form groups of tasks.
Definition: task.h:332
STL namespace.
intptr_t my_state
Definition: task_group.h:44
#define __TBB_CATCH(e)
Definition: tbb_stddef.h:284
task_handle_task(task_handle< F > &h)
Definition: task_group.h:77
#define __TBB_TRY
Definition: tbb_stddef.h:283
bool is_current_task_group_canceling()
Definition: task_group.h:237
int ref_count() const
The internal reference count.
Definition: task.h:867
bool __TBB_EXPORTED_METHOD is_group_execution_cancelled() const
Returns true if the context received cancellation request.
Base class for user-defined tasks.
Definition: task.h:589
void wait_for_all()
Wait for reference count to become one, and set reference count to zero.
Definition: task.h:789
task_group_status
Definition: task_group.h:61
task_handle(F &&f)
Definition: task_group.h:55
task_group_status wait()
Definition: task_group.h:229
void internal_run(__TBB_FORWARDING_REF(F) f)
Definition: task_group.h:113
#define __TBB_RETHROW()
Definition: tbb_stddef.h:286
void throw_exception(exception_id eid)
Versionless convenience wrapper for throw_exception_v4()
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 void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type type
void increment_ref_count()
Atomically increment reference count.
Definition: task.h:741
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

Copyright © 2005-2019 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.