21 #ifndef __TBB_parallel_scan_H 22 #define __TBB_parallel_scan_H 50 template<
typename Range,
typename Body>
60 my_body(body_,
split())
65 my_range.
begin()->~Range();
68 new( my_range.
begin() ) Range(range_);
69 my_stuff_last = stuff_last_;
75 my_stuff_last->assign(my_body);
82 template<
typename Range,
typename Body>
95 sum_node(
const Range range_,
bool left_is_final_ ) :
100 my_left_is_final(left_is_final_),
123 recycle_as_continuation();
126 task* a = my_left_is_final ? NULL : c.
create_child(my_range,*my_body,my_left,my_incoming,NULL);
127 set_ref_count( (a!=NULL)+(b!=NULL) );
136 template<
typename Range_,
typename Body_,
typename Partitioner_>
139 template<
typename Range_,
typename Body_>
145 template<
typename Range,
typename Body>
159 if( my_right_zombie && my_sum )
162 if( my_right_zombie || my_result.
my_right ) {
163 my_return_slot = &my_result;
165 destroy( my_result );
167 if( my_right_zombie && !my_sum && !my_result.
my_right ) {
168 destroy(*my_right_zombie);
169 my_right_zombie = NULL;
174 finish_scan( sum_node_type*& return_slot_, final_sum_type** sum_, sum_node_type& result_ ) :
176 my_return_slot(return_slot_),
177 my_right_zombie(NULL),
186 template<
typename Range,
typename Body,
typename Partitioner=simple_partitioner>
203 my_body(parent_.my_body),
204 my_sum(parent_.my_sum),
205 my_return_slot(&return_slot_),
206 my_parent_sum(parent_sum_),
207 my_is_final(parent_.my_is_final),
208 my_is_right_child(false),
209 my_range(parent_.my_range,
split()),
210 my_partition(parent_.my_partition,split())
215 start_scan( sum_node_type*& return_slot_,
const Range& range_, final_sum_type& body_,
const Partitioner& partitioner_) :
218 my_return_slot(&return_slot_),
221 my_is_right_child(false),
223 my_partition(partitioner_)
228 static void run(
const Range& range_, Body& body_,
const Partitioner& partitioner_ ) {
229 if( !range_.empty() ) {
230 typedef internal::start_scan<Range,Body,Partitioner> start_pass1_type;
231 internal::sum_node<Range,Body>* root = NULL;
238 temp_body->
my_body.reverse_join(body_);
241 root->my_body = temp_body;
242 root->my_incoming = NULL;
246 body_.assign(temp_body->
my_body);
248 temp_body->destroy(*temp_body);
254 template<
typename Range,
typename Body,
typename Partitioner>
256 typedef internal::finish_scan<Range,Body> finish_pass1_type;
257 finish_pass1_type*
p = my_parent_sum ?
static_cast<finish_pass1_type*
>(
parent() ) : NULL;
261 bool treat_as_stolen = my_is_right_child && (is_stolen_task() || my_body!=p->my_result.my_left_sum);
262 if( treat_as_stolen ) {
264 p->my_right_zombie = my_body =
new( allocate_root() )
final_sum_type(my_body->my_body);
267 task* next_task = NULL;
268 if( (my_is_right_child && !treat_as_stolen) || !my_range.is_divisible() || my_partition.should_execute_range(*
this) ) {
279 result =
new(allocate_additional_child_of(*my_parent_sum))
sum_node_type(my_range,my_is_final);
282 finish_pass1_type& c = *
new( allocate_continuation()) finish_pass1_type(*my_return_slot,my_sum,*result);
289 recycle_as_child_of(c);
293 my_return_slot = &result->
my_left;
294 my_is_right_child =
false;
296 my_parent_sum = result;
302 template<
typename Range,
typename Value,
typename Scan,
typename ReverseJoin>
311 , identity_element(identity)
313 , my_reverse_join(rev_join) {}
316 : my_sum(b.identity_element)
317 , identity_element(b.identity_element)
319 , my_reverse_join(b.my_reverse_join) {}
321 template<
typename Tag>
323 my_sum = my_scan(r, my_sum, tag);
327 my_sum = my_reverse_join(a.
my_sum, my_sum);
363 template<
typename Range,
typename Body>
370 template<
typename Range,
typename Body>
377 template<
typename Range,
typename Body>
384 template<
typename Range,
typename Value,
typename Scan,
typename ReverseJoin>
385 Value
parallel_scan(
const Range& range,
const Value& identity,
const Scan& scan,
const ReverseJoin& reverse_join ) {
386 internal::lambda_scan_body<Range, Value, Scan, ReverseJoin> body(identity, scan, reverse_join);
388 return body.result();
393 template<
typename Range,
typename Value,
typename Scan,
typename ReverseJoin>
395 internal::lambda_scan_body<Range, Value, Scan, ReverseJoin> body(identity, scan, reverse_join);
397 return body.result();
402 template<
typename Range,
typename Value,
typename Scan,
typename ReverseJoin>
404 internal::lambda_scan_body<Range, Value, Scan, ReverseJoin> body(identity, scan, reverse_join);
406 return body.result();
sum_node_type * my_parent_sum
static bool is_final_scan()
sum_node< Range, Body > sum_node_type
const Value & identity_element
T * begin() const
Pointer to beginning of array.
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
lambda_scan_body(lambda_scan_body &b, split)
task * execute() __TBB_override
Should be overridden by derived classes.
sum_node_type ** my_return_slot
final_sum_type **const my_sum
Base class for types that should not be assigned.
sum_node_type *& my_return_slot
final_sum_type * my_incoming
Split work to be done in the scan.
Used to indicate that the initial scan is being performed.
final_sum_type * my_right_zombie
sum_node_type & my_result
void operator()(const Range &r, Tag tag)
sum_node< Range, Body > sum_node_type
start_scan(sum_node_type *&return_slot_, const Range &range_, final_sum_type &body_, const Partitioner &partitioner_)
final_sum< Range, Body > final_sum_type
Initial task to split the work.
void const char const char int ITT_FORMAT __itt_group_sync p
Performs final scan for a leaf.
void reverse_join(lambda_scan_body &a)
void finish_construction(const Range &range_, Body *stuff_last_)
int ref_count() const
The internal reference count.
task * create_child(const Range &range_, final_sum_type &f, sum_node *n, final_sum_type *incoming_, Body *stuff_last_)
task * execute() __TBB_override
Should be overridden by derived classes.
Body * my_stuff_last
Where to put result of last subrange, or NULL if not last subrange.
final_sum< Range, Body > final_sum_type
static void run(const Range &range_, Body &body_, const Partitioner &partitioner_)
task * execute() __TBB_override
Should be overridden by derived classes.
void parallel_scan(const Range &range, Body &body)
Parallel prefix with default partitioner.
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 poison_pointer(T *__TBB_atomic &)
const ReverseJoin & my_reverse_join
#define __TBB_DEFAULT_PARTITIONER
static internal::allocate_root_proxy allocate_root()
Returns proxy for overloaded new that allocates a root task.
Partitioner::partition_type my_partition
static void spawn_root_and_wait(task &root)
Spawn task allocated by allocate_root, wait for it to complete, and deallocate it.
lambda_scan_body(const Value &identity, const Scan &scan, const ReverseJoin &rev_join)
final_sum_type * my_left_sum
Base class for user-defined tasks.
void assign(lambda_scan_body &b)
final_sum< Range, Body > final_sum_type
task * execute() __TBB_override
Should be overridden by derived classes.
Dummy type that distinguishes splitting constructor from copy constructor.
void recycle_as_child_of(task &new_parent)
Change this to be a child of new_parent.
static bool is_final_scan()
Used to indicate that the final scan is being performed.
aligned_space< Range > my_range
sum_node(const Range range_, bool left_is_final_)
finish_scan(sum_node_type *&return_slot_, final_sum_type **sum_, sum_node_type &result_)