Thread::wait() doesn't always wait


#1

Jules,

I noticed that if I call wait() on a thread and then notify() it, the thread remains signalled, so that subsequent calls to wait() on the thread immediately fall through, i.e. it doesn’t wait to be notified again. Is this correct behavior?

Perhaps the following change could be implemented, to ensure that the signal is reset:

bool Thread::wait (const int timeOutMilliseconds) const { // Start Modification defaultEvent_.reset(); // End Modification return defaultEvent_.wait (timeOutMilliseconds); }

This works in my code on Windows, although I haven’t tried it on other platforms yet.

Originally, I thought it would be best to modify the Windows-specific code for WaitableEvent thusly:

bool WaitableEvent::wait (const int timeOutMillisecs) const throw() { // Start Modification ResetEvent (internal); // End Modification return WaitForSingleObject (internal, timeOutMillisecs) == WAIT_OBJECT_0; }

But for some reason the event doesn’t get signalled and it times out…

Anyway, I thought I’d mention this.


#2

no, I think you must have got something confused there. It gets reset automatically. If it didn’t work there’d be problems with audio, midi, timers, threads, etc…


#3

OK, thanks Jules. I’ve probably just @*$&ed something up then! :stuck_out_tongue:


#4

OK, Jules, I see what was happening and I think it requires a tweak in JUCE. Of course, that’s what I said last time… :stuck_out_tongue:

I have a thread that isn’t always running, but its instantiation persists. The first time I start the thread and call wait(), it gets its notification properly and then I stop the thread. The next time I start the thread and call wait(), it doesn’t wait… and here’s why…

In stopThread() there is a call to notify(), which signals the WaitableEvent. When startThread() is called again, the event is still signalled and a wait will just drop through. I think it needs to reset the event:

[code]void Thread::startThread()
{
const ScopedLock sl (startStopLock);

threadShouldExit_ = false;

if (threadHandle_ == 0)
{
    threadHandle_ = juce_createThread ((void*)this);
    juce_setThreadPriority (threadHandle_, threadPriority_);
    startSuspensionEvent_.signal();
}

// Start Mod – maybe this needs to come earlier on, but I think
// it needs to be called somewhere in here!
defaultEvent_.reset();
// End Mod
}[/code]

Does it make sense this time, Jules, or am I missing something again?

Thanks.


#5

my moneys on juce!

fucks sake, tracktion works to a reasonable extent does it not?

I use juce’s concurrency constructs all the time and it works.

concurrent programming 101?

best course in uni!


#6

but I’m drunk.


#7

[quote=“Randy”]OK, Jules, I see what was happening and I think it requires a tweak in JUCE. Of course, that’s what I said last time… :stuck_out_tongue:

I have a thread that isn’t always running, but its instantiation persists. The first time I start the thread and call wait(), it gets its notification properly and then I stop the thread. The next time I start the thread and call wait(), it doesn’t wait… and here’s why…

In stopThread() there is a call to notify(), which signals the WaitableEvent. When startThread() is called again, the event is still signalled and a wait will just drop through. I think it needs to reset the event:

[code]void Thread::startThread()
{
const ScopedLock sl (startStopLock);

threadShouldExit_ = false;

if (threadHandle_ == 0)
{
    threadHandle_ = juce_createThread ((void*)this);
    juce_setThreadPriority (threadHandle_, threadPriority_);
    startSuspensionEvent_.signal();
}

// Start Mod – maybe this needs to come earlier on, but I think
// it needs to be called somewhere in here!
defaultEvent_.reset();
// End Mod
}[/code]

Does it make sense this time, Jules, or am I missing something again?

Thanks.[/quote]

Well not really… the event’s just there for convenience - how you choose to signal and reset it is up to you, it’s not the job of the Thread class to do that kind of thing. Why not just call wait (1) at the start of your thread to reset it - or use your own event object and reset that at the start.


#8