| 740 | }; |
| 741 | |
| 742 | void task_arena_base::internal_execute( internal::delegate_base& d) const { |
| 743 | __TBB_ASSERT(my_arena, NULL); |
| 744 | generic_scheduler* s = governor::local_scheduler(); |
| 745 | __TBB_ASSERT(s, "Scheduler is not initialized"); |
| 746 | // TODO: is it safe to assign slot to a scheduler which is not yet switched? |
| 747 | // TODO TEMP: one master, make more masters |
| 748 | if( s->my_arena == my_arena || (!__TBB_load_with_acquire(my_arena->my_slots[0].my_scheduler) |
| 749 | && as_atomic(my_arena->my_slots[0].my_scheduler).compare_and_swap(s, NULL ) == NULL) ) { |
| 750 | cpu_ctl_env_helper cpu_ctl_helper; |
| 751 | cpu_ctl_helper.set_env( __TBB_CONTEXT_ARG1(my_context) ); |
| 752 | #if TBB_USE_EXCEPTIONS |
| 753 | try { |
| 754 | #endif |
| 755 | //TODO: replace dummy tasks for workers as well to avoid using of the_dummy_context |
| 756 | nested_arena_context scope(s, my_arena, !my_master_slots); |
| 757 | d(); |
| 758 | #if TBB_USE_EXCEPTIONS |
| 759 | } catch(...) { |
| 760 | cpu_ctl_helper.restore_default(); // TODO: is it needed on Windows? |
| 761 | if( my_version_and_traits & exact_exception_flag ) throw; |
| 762 | else { |
| 763 | task_group_context exception_container( task_group_context::isolated, |
| 764 | task_group_context::default_traits & ~task_group_context::exact_exception ); |
| 765 | exception_container.register_pending_exception(); |
| 766 | __TBB_ASSERT(exception_container.my_exception, NULL); |
| 767 | exception_container.my_exception->throw_self(); |
| 768 | } |
| 769 | } |
| 770 | #endif |
| 771 | } else { |
| 772 | concurrent_monitor::thread_context waiter; |
| 773 | #if __TBB_TASK_GROUP_CONTEXT |
| 774 | task_group_context exec_context( task_group_context::isolated, my_version_and_traits & exact_exception_flag ); |
| 775 | #if __TBB_FP_CONTEXT |
| 776 | exec_context.copy_fp_settings( *my_context ); |
| 777 | #endif |
| 778 | #endif |
| 779 | auto_empty_task root(__TBB_CONTEXT_ARG(s, &exec_context)); |
| 780 | root.prefix().ref_count = 2; |
| 781 | my_arena->enqueue_task( *new( task::allocate_root(__TBB_CONTEXT_ARG1(exec_context)) ) |
| 782 | delegated_task(d, my_arena->my_exit_monitors, &root), |
| 783 | 0, s->my_random ); // TODO: priority? |
| 784 | do { |
| 785 | my_arena->my_exit_monitors.prepare_wait(waiter, (uintptr_t)&d); |
| 786 | if( __TBB_load_with_acquire(root.prefix().ref_count) < 2 ) { |
| 787 | my_arena->my_exit_monitors.cancel_wait(waiter); |
| 788 | break; |
| 789 | } |
| 790 | else if( !__TBB_load_with_acquire(my_arena->my_slots[0].my_scheduler) // TODO: refactor into a function? |
| 791 | && as_atomic(my_arena->my_slots[0].my_scheduler).compare_and_swap(s, NULL ) == NULL ) { |
| 792 | my_arena->my_exit_monitors.cancel_wait(waiter); |
| 793 | nested_arena_context scope(s, my_arena, !my_master_slots); |
| 794 | s->local_wait_for_all(root, NULL); |
| 795 | #if TBB_USE_EXCEPTIONS |
| 796 | __TBB_ASSERT( !exec_context.my_exception, NULL ); // exception can be thrown above, not deferred |
| 797 | #endif |
| 798 | __TBB_ASSERT( root.prefix().ref_count == 0, NULL ); |
| 799 | break; |
nothing calls this directly
no test coverage detected