|
Boost : |
From: Alexander Terekhov (terekhov_at_[hidden])
Date: 2002-10-18 08:31:41
"Hillel Y. Sims" wrote:
[...]
> (I like the notion of predicate-based wait() wrapper though, might help to
> eliminate some confusion over whether/why one should say "while (!pred)
> cv.wait()" vs. "do { cv.wait() } while (!pred)".)
Uhmm. The later one is somewhat less applicable but is perfectly OK
in e.g. signal&wait-on-the-same-CV situations... Another application
for NON-"while (!pred) cv.wait()"-loops is when the predicate is
nothing but "timedout-or-not" timedwait()'s status: [from my recent
DESIGN-futex-CV.cpp]
<snip>
}; //*** class futex_condvar
//*** yet another "tennis" (but with futex_condvars this time)
#include <ctime>
#include <iostream>
using namespace std;
enum GAME_STATE {
START_GAME,
PLAYER_A, // Player A plays the ball
PLAYER_B, // Player B plays the ball
GAME_OVER,
ONE_PLAYER_GONE,
BOTH_PLAYERS_GONE
} eGameState;
mutex mtxGameStateLock;
futex_condvar cndGameStateChange;
futex_condvar cndMainThreadSleep;
const char* id( GAME_STATE ePlayer ) {
assert( PLAYER_A == ePlayer || PLAYER_B == ePlayer );
return ( PLAYER_A == ePlayer ) ? "PLAYER A" : "PLAYER B";
}
GAME_STATE another( GAME_STATE ePlayer ) {
assert( PLAYER_A == ePlayer || PLAYER_B == ePlayer );
return ( PLAYER_A == ePlayer ) ? PLAYER_B : PLAYER_A;
}
extern "C" void* play( void* pPlayer ) {
GAME_STATE ePlayer = *static_cast< GAME_STATE* >( pPlayer );
mutex::guard guard( mtxGameStateLock );
while ( eGameState < GAME_OVER ) {
cout << id( ePlayer ) << "\n";
eGameState = another( ePlayer );
cndGameStateChange.signal();
do {
cndGameStateChange.wait( mtxGameStateLock );
if ( another( ePlayer ) == eGameState )
cout << "\n----" << id( ePlayer ) << ": SPURIOUS WAKEUP!!!\n";
} while ( another( ePlayer ) == eGameState );
}
eGameState = static_cast< GAME_STATE >( eGameState+1 );
cout << id( ePlayer ) << " GONE\n";
cndGameStateChange.broadcast();
return 0;
}
GAME_STATE ePlayerA = PLAYER_A;
GAME_STATE ePlayerB = PLAYER_B;
int main() {
pthread_t thid;
eGameState = START_GAME;
pthread_create( &thid,0,&play,static_cast< void* >( &ePlayerA ) );
pthread_create( &thid,0,&play,static_cast< void* >( &ePlayerB ) );
mutex::guard guard( mtxGameStateLock );
for ( int i = 0; i < 10; ++i ) {
timespec abstime;
int status = clock_gettime( CLOCK_REALTIME, &abstime );
assert( !status );
if ( 1000000000L < (abstime.tv_nsec += 100000000L) ) {
abstime.tv_nsec %= 100000000L;
++abstime.tv_sec;
}
while ( !cndMainThreadSleep.timedwait( mtxGameStateLock, abstime ) ) ;
cout << "\nMAIN: TIC-TAC [" << 9-i << "]\n\n";
}
eGameState = GAME_OVER;
cndGameStateChange.broadcast();
do { cndGameStateChange.wait( mtxGameStateLock ); }
while ( BOTH_PLAYERS_GONE != eGameState );
cout << "\nGAME OVER\n";
}
regards,
alexander.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk