Cancel Time::waitForMillisecondCounter in thread?


#1

Hi!

I’ve made a sequencer, which uses Time::waitForMillisecondCounter to precisely wait between consecutive events. This is running in its own thread.

It works beautifully, but when I want to stop the thread during playback, my option is to either wait for the waitForMillisecondCounter to run its course by giving its time to stopThread(), or to call stopThread with a much shorter time, but then I get the “Bad Karma” assertion in juce_thread.cpp’s stopThread definition.

As far as I understand it, to avoid the “Bad Karma” warning, I have to find a way to stop the waitForMillisecondCounter to run its course, but I don’t see any way to do that.

Am I missing something? I guess I can live with the Bad Karma, but the OCD programmer in me wants to do this “The right way” :slight_smile:


#2

No, you really, really don’t ever want to kill a thread!

In something like the tracktion engine we only use it to wait for a maximum of a few milliseconds, which gives you a chance to check whether the thread should exit or not. I don’t think it really makes sense to use that function to wait for long periods of time.


#3

Thank you for the warning and tip Jules!

Indeed it is 5 more lines of code to wait in say 100ms increments and check threadShouldExit() in between, I should have thought of that, it works a charm.


#4

Just use thread::wait, which automatically ends when the thread should stop.


#5

I may be pointing out the obvious but my understanding is that waitForMillisecondCounter can be more precise because for the last few milliseconds it waits actively:

void Time::waitForMillisecondCounter (const uint32 targetTime) noexcept
{
    for (;;)
    {
        const uint32 now = getMillisecondCounter();

        if (now >= targetTime)
            break;

        const int toWait = (int) (targetTime - now);

        if (toWait > 2)
        {
            Thread::sleep (jmin (20, toWait >> 1));
        }
        else
        {
            // xxx should consider using mutex_pause on the mac as it apparently
            // makes it seem less like a spinlock and avoids lowering the thread pri.
            for (int i = 10; --i >= 0;)
                Thread::yield();
        }
    }
}

I use it to wait between sending messages in sparse timeline sequences.