Boost logo

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