Conceptually, this method should be a member of class scheduler. But doing so would force us to publish class scheduler in the headers. */
| 605 | /** Conceptually, this method should be a member of class scheduler. |
| 606 | But doing so would force us to publish class scheduler in the headers. */ |
| 607 | void generic_scheduler::local_spawn( task& first, task*& next ) { |
| 608 | __TBB_ASSERT( governor::is_set(this), NULL ); |
| 609 | if ( &first.prefix().next == &next ) { |
| 610 | // Single task is being spawned |
| 611 | size_t T = prepare_task_pool( 1 ); |
| 612 | my_arena_slot->task_pool_ptr[T] = prepare_for_spawning( &first ); |
| 613 | commit_spawned_tasks( T + 1 ); |
| 614 | } |
| 615 | else { |
| 616 | // Task list is being spawned |
| 617 | task *arr[min_task_pool_size]; |
| 618 | fast_reverse_vector<task*> tasks(arr, min_task_pool_size); |
| 619 | task *t_next = NULL; |
| 620 | for( task* t = &first; ; t = t_next ) { |
| 621 | // If t is affinitized to another thread, it may already be executed |
| 622 | // and destroyed by the time prepare_for_spawning returns. |
| 623 | // So milk it while it is alive. |
| 624 | bool end = &t->prefix().next == &next; |
| 625 | t_next = t->prefix().next; |
| 626 | tasks.push_back( prepare_for_spawning(t) ); |
| 627 | if( end ) |
| 628 | break; |
| 629 | } |
| 630 | size_t num_tasks = tasks.size(); |
| 631 | size_t T = prepare_task_pool( num_tasks ); |
| 632 | tasks.copy_memory( my_arena_slot->task_pool_ptr + T ); |
| 633 | commit_spawned_tasks( T + num_tasks ); |
| 634 | } |
| 635 | if ( !in_arena() ) |
| 636 | enter_arena(); |
| 637 | my_arena->advertise_new_work</*Spawned=*/true>(); |
| 638 | assert_task_pool_valid(); |
| 639 | } |
| 640 | |
| 641 | void generic_scheduler::local_spawn_root_and_wait( task& first, task*& next ) { |
| 642 | __TBB_ASSERT( governor::is_set(this), NULL ); |
no test coverage detected