20

I am developing an application in which I do multithreading. One of my worker threads displays images on the widget. Another thread plays sound. I want to stop/suspend/pause/sleep the threads on a button click event. It is same as when we click on video player play/pause button. I am developing my application in c++ on linux platform using the pthread library for threading.

Can somebody tell me how I achieve threads pause/suspend?

deft_code
  • 57,255
  • 29
  • 141
  • 224
Muhammad Ummar
  • 3,541
  • 6
  • 40
  • 71

2 Answers2

31

You can use a mutex, condition variable, and a shared flag variable to do this. Let's assume these are defined globally:

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int play = 0;

You could structure your playback code like this:

for(;;) { /* Playback loop */
    pthread_mutex_lock(&lock);
    while(!play) { /* We're paused */
        pthread_cond_wait(&cond, &lock); /* Wait for play signal */
    }
    pthread_mutex_unlock(&lock);
    /* Continue playback */
}

Then, to play you can do this:

pthread_mutex_lock(&lock);
play = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);

And to pause:

pthread_mutex_lock(&lock);
play = 0;
pthread_mutex_unlock(&lock);
Left For Archive
  • 2,626
  • 1
  • 18
  • 19
  • It's not really safe to ever access a globally shared variable in a multi-threaded environment. Lock the mutex before checking for `!play` and also use a mutex when setting `play = 0;`. In practice this will not be an issue on a single core system but it is always better to write correct/future-proof code. – deft_code Jan 21 '11 at 17:55
  • In practice it won't be an issue for most multi-core systems either, though you're right—this does need at least a couple memory barriers. Without them, the pause could take an arbitrarily long time to take effect. Of course, just locking the mutex is fine too, and I'll edit this answer to do that. :) – Left For Archive Jan 22 '11 at 00:59
  • @deft_code Answer updated! Please see my previous comment though. – Left For Archive Jan 22 '11 at 02:17
  • Reading or writing a variable up to the cpu's max word size is generally atomic, and changing a single bit as in this case is practically atomic by definition. The mutex here has almost no effect: with or without it, if two threads try to change `play` at the same time, then one will overwrite the other, and if a read and a write happen at the same time then the read can return either value. The only guarantee you really need here is that `play` gets set (e.g. via a memory barrier) *before* pthread_cond_signal releases the pthread_cond_wait. Can any pthread implementation *not* guarantee that? – Matt Jun 25 '11 at 18:57
  • 2
    For more info see this question and answers: http://stackoverflow.com/questions/1003190/not-locking-mutex-for-pthread-cond-timedwait-and-pthread-cond-signal-on-linux ... In short, you *have* to lock the mutex around pthread_cond_wait() and it is recommended around pthread_cond_signal(). – Matt Jun 25 '11 at 19:15
  • @Matt If a signal hits a condition variable and no one's there to wait for it, it doesn't cause a wakeup. Locking the mutex before calling pthread_cond_signal guarantees either (1) the playback thread hasn't noticed it's paused yet, or (2) the playback thread is currently waiting for the signal to unpause. I agree—locking the mutex just to set an int is pointless on any reasonable machine, though it's also fairly harmless. – Left For Archive Jun 30 '11 at 21:04
  • I'm fairly sure that you can alternatively use if(!play) rather than while(!play) -- the pthread_cond_wait command will block the thread's execution until the condition is satisfied. – Ben J Sep 20 '11 at 00:07
  • 1
    @Ben You can't rely on that. `pthread_cond_wait` can wake up before the signal's sent. You have to recheck the condition. See: http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_wait.html – Left For Archive Sep 26 '11 at 21:40
3

You have your threads poll for "messages" from the UI at regular interval. In other words, UI in one thread posts action messages to the worker threads e.g. audio/video.

jldupont
  • 93,734
  • 56
  • 203
  • 318
  • 2
    This is probably the best answer here. The problem is it's so thin on details that it doesn't really answer the question. – deft_code Jan 21 '11 at 17:57