17 #ifndef __TBB_parallel_scan_H 18 #define __TBB_parallel_scan_H 20 #define __TBB_parallel_scan_H_include_area 49 template<
typename Range,
typename Body>
59 my_body(body_,
split())
64 my_range.begin()->~Range();
67 new( my_range.begin() ) Range(range_);
68 my_stuff_last = stuff_last_;
74 my_stuff_last->assign(my_body);
81 template<
typename Range,
typename Body>
94 sum_node(
const Range range_,
bool left_is_final_ ) :
99 my_left_is_final(left_is_final_),
122 recycle_as_continuation();
125 task* a = my_left_is_final ? NULL : c.
create_child(my_range,*my_body,my_left,my_incoming,NULL);
126 set_ref_count( (a!=NULL)+(b!=NULL) );
135 template<
typename Range_,
typename Body_,
typename Partitioner_>
138 template<
typename Range_,
typename Body_>
144 template<
typename Range,
typename Body>
158 if( my_right_zombie && my_sum )
161 if( my_right_zombie || my_result.
my_right ) {
162 my_return_slot = &my_result;
164 destroy( my_result );
166 if( my_right_zombie && !my_sum && !my_result.
my_right ) {
167 destroy(*my_right_zombie);
168 my_right_zombie = NULL;
173 finish_scan( sum_node_type*& return_slot_, final_sum_type** sum_, sum_node_type& result_ ) :
175 my_return_slot(return_slot_),
176 my_right_zombie(NULL),
185 template<
typename Range,
typename Body,
typename Partitioner=simple_partitioner>
202 my_body(parent_.my_body),
203 my_sum(parent_.my_sum),
204 my_return_slot(&return_slot_),
205 my_parent_sum(parent_sum_),
206 my_is_final(parent_.my_is_final),
207 my_is_right_child(false),
208 my_range(parent_.my_range,
split()),
209 my_partition(parent_.my_partition,split())
214 start_scan( sum_node_type*& return_slot_,
const Range& range_, final_sum_type& body_,
const Partitioner& partitioner_) :
217 my_return_slot(&return_slot_),
220 my_is_right_child(false),
222 my_partition(partitioner_)
227 static void run(
const Range& range_, Body& body_,
const Partitioner& partitioner_ ) {
228 if( !range_.empty() ) {
237 temp_body->
my_body.reverse_join(body_);
245 body_.assign(temp_body->
my_body);
247 temp_body->destroy(*temp_body);
253 template<
typename Range,
typename Body,
typename Partitioner>
256 finish_pass1_type*
p = my_parent_sum ?
static_cast<finish_pass1_type*
>(
parent() ) : NULL;
260 bool treat_as_stolen = my_is_right_child && (is_stolen_task() || my_body!=p->my_result.my_left_sum);
261 if( treat_as_stolen ) {
263 p->my_right_zombie = my_body =
new( allocate_root() )
final_sum_type(my_body->my_body);
266 task* next_task = NULL;
267 if( (my_is_right_child && !treat_as_stolen) || !my_range.is_divisible() || my_partition.should_execute_range(*
this) ) {
278 result =
new(allocate_additional_child_of(*my_parent_sum))
sum_node_type(my_range,my_is_final);
281 finish_pass1_type& c = *
new( allocate_continuation()) finish_pass1_type(*my_return_slot,my_sum,*result);
288 recycle_as_child_of(c);
292 my_return_slot = &result->
my_left;
293 my_is_right_child =
false;
295 my_parent_sum = result;
301 template<
typename Range,
typename Value,
typename Scan,
typename ReverseJoin>
310 , identity_element(identity)
312 , my_reverse_join(rev_join) {}
315 : my_sum(b.identity_element)
316 , identity_element(b.identity_element)
318 , my_reverse_join(b.my_reverse_join) {}
320 template<
typename Tag>
322 my_sum = my_scan(r, my_sum, tag);
326 my_sum = my_reverse_join(a.
my_sum, my_sum);
362 template<
typename Range,
typename Body>
369 template<
typename Range,
typename Body>
376 template<
typename Range,
typename Body>
383 template<
typename Range,
typename Value,
typename Scan,
typename ReverseJoin>
384 Value
parallel_scan(
const Range& range,
const Value& identity,
const Scan& scan,
const ReverseJoin& reverse_join ) {
392 template<
typename Range,
typename Value,
typename Scan,
typename ReverseJoin>
401 template<
typename Range,
typename Value,
typename Scan,
typename ReverseJoin>
413 #undef __TBB_parallel_scan_H_include_area sum_node_type * my_parent_sum
Base class for types that should not be assigned.
void reverse_join(lambda_scan_body &a)
sum_node_type *& my_return_slot
void poison_pointer(T *__TBB_atomic &)
Partitioner::partition_type my_partition
finish_scan(sum_node_type *&return_slot_, final_sum_type **sum_, sum_node_type &result_)
Body * my_stuff_last
Where to put result of last subrange, or NULL if not last subrange.
lambda_scan_body(const Value &identity, const Scan &scan, const ReverseJoin &rev_join)
start_scan(sum_node_type *&return_slot_, const Range &range_, final_sum_type &body_, const Partitioner &partitioner_)
task * execute() __TBB_override
Should be overridden by derived classes.
void operator()(const Range &r, Tag tag)
void assign(lambda_scan_body &b)
static bool is_final_scan()
static bool is_final_scan()
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 parent
void parallel_scan(const Range &range, Body &body)
Parallel prefix with default partitioner.
final_sum_type * my_incoming
#define __TBB_DEFAULT_PARTITIONER
final_sum_type * my_left_sum
const ReverseJoin & my_reverse_join
task * create_child(const Range &range_, final_sum_type &f, sum_node *n, final_sum_type *incoming_, Body *stuff_last_)
void finish_construction(const Range &range_, Body *stuff_last_)
sum_node(const Range range_, bool left_is_final_)
task * execute() __TBB_override
Should be overridden by derived classes.
Used to indicate that the final scan is being performed.
final_sum_type * my_right_zombie
final_sum< Range, Body > final_sum_type
final_sum< Range, Body > final_sum_type
Split work to be done in the scan.
Used to indicate that the initial scan is being performed.
aligned_space< Range > my_range
int ref_count() const
The internal reference count.
final_sum< Range, Body > final_sum_type
static internal::allocate_root_proxy allocate_root()
Returns proxy for overloaded new that allocates a root task.
sum_node< Range, Body > sum_node_type
lambda_scan_body(lambda_scan_body &b, split)
static void spawn_root_and_wait(task &root)
Spawn task allocated by allocate_root, wait for it to complete, and deallocate it.
Initial task to split the work.
Performs final scan for a leaf.
sum_node< Range, Body > sum_node_type
Dummy type that distinguishes splitting constructor from copy constructor.
task * execute() __TBB_override
Should be overridden by derived classes.
void recycle_as_child_of(task &new_parent)
Change this to be a child of new_parent.
task * execute() __TBB_override
Should be overridden by derived classes.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
final_sum_type **const my_sum
static void run(const Range &range_, Body &body_, const Partitioner &partitioner_)
sum_node_type & my_result
const Value & identity_element
void const char const char int ITT_FORMAT __itt_group_sync p
Base class for user-defined tasks.
sum_node_type ** my_return_slot