How to sleep or pause a PThread in c on Linux
Asked Answered
H

2

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?

Horrorstruck answered 22/10, 2009 at 10:48 Comment(1)
Maybe you can try my solution based on realtime signals: https://mcmap.net/q/663107/-how-to-pause-a-pthread-any-time-i-wantBough
M
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);
Mears answered 19/11, 2009 at 4:8 Comment(8)
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.Ralleigh
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. :)Mears
@Ralleigh Answer updated! Please see my previous comment though.Mears
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?Overstate
For more info see this question and answers: #1003690 ... In short, you have to lock the mutex around pthread_cond_wait() and it is recommended around pthread_cond_signal().Overstate
@Overstate 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.Mears
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.Twist
@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: pubs.opengroup.org/onlinepubs/7908799/xsh/…Mears
A
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.

Alisun answered 22/10, 2009 at 10:52 Comment(1)
This is probably the best answer here. The problem is it's so thin on details that it doesn't really answer the question.Ralleigh

© 2022 - 2024 — McMap. All rights reserved.