I have this race condition with an audio playback class, where every time I start playback I set keepPlaying as true, and false when I stop.
The problem happens when I stop() immediately after I start, and the keepPlaying flag is set to false, then reset to true again.
I could put a delay in stop(), but I don't think that's a very good solution. Should I use conditional variable to make stop() wait until keepPlaying is true?
How would you normally solve this problem?
#include <iostream>
#include <thread>
using namespace std;
class AudioPlayer
{
bool keepRunning;
thread thread_play;
public:
AudioPlayer(){ keepRunning = false; }
~AudioPlayer(){ stop(); }
void play()
{
stop();
// keepRunning = true; // A: this works OK
thread_play = thread(&AudioPlayer::_play, this);
}
void stop()
{
keepRunning = false;
if (thread_play.joinable()) thread_play.join();
}
void _play()
{
cout << "Playing: started\n";
keepRunning = true; // B: this causes problem
while(keepRunning)
{
this_thread::sleep_for(chrono::milliseconds(100));
}
cout << "Playing: stopped\n";
}
};
int main()
{
AudioPlayer ap;
ap.play();
ap.play();
ap.play();
return 0;
}
Output:
$ ./test
Playing: started
(pause indefinitely...)