signalThreadShouldExit & startThread


#1

If you have a Thread and flag it to Exit with signalThreadShouldExit() and then startThread() fairly quickly… the Thread may not start… I’ve written my own code to make sure the thread isn’t running before trying to startThread()… but shouldn’t startThread() check if the shouldExit flag is set and if the thread is already running… wait for it to stop before starting the Thread?

Cheers,

Rail


#2

I would rather expect it to not trying to start the thread, because otherwise you wait in the startThread for the stopThread… sounds like you could get into infinite problems…


#3

If you’re waiting for it to not be running before you try and start the Thread… I don’t see how you could get into a loop :wink:

Rail


#4

Why are you using signalThreadShouldExit rather than stopThread?


#5

yes, I am aware, that’s why I put could and in italic, to put double doubt in it.
But waiting for something to stop to schedule it to start sounds strange to me, and depending how this workflow is triggered it ends up waiting for on and of.
It sounds like Adrian Monk switching the light switch on and off 5 times, before he can leave the flat…


#6

Why would that matter? stopThread() calls signalThreadShouldExit() (and I don’t necessarily want to wait for it to stop… I don’t always start the Thread again right away) ??

Cheers,

Rail


#7

I don’t think so, though exactly what it should do probably does need defining more clearly.

What happens at the moment is that startThread resets the exit flag regardless of whether or not there’s a thread currently running. If one is already running, then it returns, so if you were to call signalThreadShouldExit and then startThread quickly, the existing thread may carry on running if it doesn’t check the flag in time.

But yes, you could hit a race condition if startThread resets the flag, and then the thread exits before it gets chance to check whether the thread is still running. However, is that actually wrong? If the startThread method had executed fractionally sooner then the result would be the same anyway.

There are a whole bunch of subtle edge cases here and I’m not sure there’s an obviously “correct” behaviour, so thoughts welcome!


#8

Let me explain my use case…

I have a Groove player with a PlayHead (insertion point)… and if you mouse click in the timeline while in playback - playback is stopped…

m_PlayheadThread.signalThreadShouldExit();

and after the new location is calculated, playback is re-started from the position where the click occurred in the Timeline…

m_PlayheadThread.startThread (PLAYHEADTHREADPRIORITY);

However, playback can also be started and stopped by using the spacebar or the Play/Stop button.

If I check the m_bIsPlaying flag and m_PlayheadThread.isThreadRunning() I can wait before starting the Thread.

Without checking the flag and if the Thread was still running, it would not always restart - so the Insertion Point would stop moving.

Cheers,

Rail


#9

TBH I wouldn’t use the thread being started or stopped to represent play state. Starting/stopping involves a fair bit of overhead - better to keep a thread running all the time, and just use a flag (or message queue) to give it instructions about whether to play or stop.


#10

well in general when the user clicks the Play/Stop button I want the Thread to start/stop running… so it’s not running when there’s no groove playing (and it’s getting external MIDI triggers)… so I’m re-using the same methods… and it seems to work really well… so I’m not sure I want to change it :wink:

Cheers,

Rail


#11

Well then I think doing

m_PlayheadThread.signalThreadShouldExit();

then

m_PlayheadThread.stopThread (timeout);
m_PlayheadThread.startThread (PLAYHEADTHREADPRIORITY);

will achieve what you want. Most of the time stopThread will be nearly instantaneous (as the previous call to signalThreadShouldExit will have stopped the thread already), but it will wait if required.

Jules’ suggestion is the way to go though.


#12

Right, I already have a work-around… I just thought it may be something that startThread() should check… but that’s up to y’all. It just seemed wrong that I needed to deal with it.

Cheers,

Rail


#13

I think all is said, but for the records, if you use the BufferingAudioSource, they use the TimeSliceThread, which uses a WaitableEvent semaphore. So if it the sources are not pulling audio, the threads are using no resources at all, without stopping and restarting them…


#14

I wouldn’t start and stop a thread from user interaction like this, better to have the thread running but paused on a condition or waitable. This way it’s safer to control and lighter on resources.


#15

Okay - I just paused the Thread on a mouse click… when I start and stop using the play button or the space bar I stop/start the Thread.

Cheers,

Rail