| 215 | } |
| 216 | |
| 217 | void interface5::internal::task_base::destroy( task& victim ) { |
| 218 | // 1 may be a guard reference for wait_for_all, which was not reset because |
| 219 | // of concurrent_wait mode or because prepared root task was not actually used |
| 220 | // for spawning tasks (as in structured_task_group). |
| 221 | __TBB_ASSERT( (intptr_t)victim.prefix().ref_count <= 1, "Task being destroyed must not have children" ); |
| 222 | __TBB_ASSERT( victim.state()==task::allocated, "illegal state for victim task" ); |
| 223 | task* parent = victim.parent(); |
| 224 | victim.~task(); |
| 225 | if( parent ) { |
| 226 | __TBB_ASSERT( parent->state()!=task::freed && parent->state()!=task::ready, |
| 227 | "attempt to destroy child of running or corrupted parent?" ); |
| 228 | // 'reexecute' and 'executing' are also signs of a race condition, since most tasks |
| 229 | // set their ref_count upon entry but "es_ref_count_active" should detect this |
| 230 | parent->internal_decrement_ref_count(); |
| 231 | // Even if the last reference to *parent is removed, it should not be spawned (documented behavior). |
| 232 | } |
| 233 | governor::local_scheduler()->free_task<no_cache>( victim ); |
| 234 | } |
| 235 | |
| 236 | void task::spawn_and_wait_for_all( task_list& list ) { |
| 237 | generic_scheduler* s = governor::local_scheduler(); |
no test coverage detected