void private_worker::run() { if( my_state.compare_and_swap( st_normal, st_init )==st_init ) { ::rml::job& j = *my_client.create_one_job(); --my_server.my_slack; while( my_state==st_normal ) { if( my_server.my_slack>=0 ) { my_client.process(j); } else { thread_monitor::cookie c; // Prepare to wait my_thread_monitor.prepare_wait(c); // Check/set the invariant for sleeping if( my_state==st_normal && my_server.try_insert_in_asleep_list(*this) ) { my_thread_monitor.commit_wait(c); // Propagate chain reaction if( my_server.has_sleepers() ) my_server.wake_some(0); } else { // Invariant broken my_thread_monitor.cancel_wait(); } } } my_client.cleanup(j); ++my_server.my_slack; } my_server.remove_server_ref(); }
void ThreadState::loop() { for(;;) { ++clock; if( ack==request ) { thread_monitor::cookie c; monitor.prepare_wait(c); if( ack==request ) { REMARK("%p: request=%d ack=%d\n", this, request, ack ); monitor.commit_wait(c); } else monitor.cancel_wait(); } else { // Throw in delay occasionally switch( request%8 ) { case 0: case 1: case 5: rml::internal::thread_monitor::yield(); } int r = request; ack = request; if( !r ) return; } } }
void private_worker::start_shutdown() { state_t s; // Transition from st_init or st_normal to st_plugged or st_quit do { s = my_state; __TBB_ASSERT( s==st_init||s==st_normal, NULL ); } while( my_state.compare_and_swap( s==st_init? st_plugged : st_quit, s )!=s ); if( s==st_normal ) { // May have invalidated invariant for sleeping, so wake up the thread. // Note that the notify() here occurs without maintaining invariants for my_slack. // It does not matter, because my_state==st_quit overrides checking of my_slack. my_thread_monitor.notify(); } }