This is a bit of a noob question, but when it comes to threading I think I’m a perpetual noob…
I need something to call a function, but in a delayed way (delayed x miliseconds). The function should be called in a thread that can take some time without blocking other things.
Right now I’m using the ThreadPool to call the functions, but I want to delay the actual function calls, and as far as I know I shouldn’t be blocking the threads in the ThreadPool - right??.
Browsing through the codebase I looked at Timer, WaitableObject, the Message stuff and I just get more confused. Especially Timer seems quite complex! Any help would be really welcome.
If you don’t need a specific time you can have a look at AsyncUpdater. Also, Timer is rather easy to implement:
class MyClass : public Timer
{
public:
void someFunction()
{
// [...]
if (somethingToDoInTheFuture)
startTimer(100); // do Job in 100 ms
}
void timerCallback()
{
// do something
stopTimer();
}
};
I read somewhere here that the first timer callback might come earlier than the time given. Don’t know if this is still the case, but if it is a problem you can use a smaller timer Intervall and save a start time (Time::getMillisecondCounter()) and check whether a given time elapsed.
I don’t think that was ever the case… Timers can get delayed by other activity on the message thread, so they can sometimes fire too late, but I don’t think they’ll ever fire early, at least not by a significant interval.
Hmm, okay, that seems like a great idea, but then the cleanup is still missing:
I would like to be able to create a new call object and have it destroy itself when it’s done.
I.e. something like
class MyFunction : public DelayedFunctionCall
{
virtual void Call()
{
// do something here
}
}
new MyFunction(); // will get cleaned up automatically.... :-/
Well, tbh I was wondering if this couldn’t be done with the ThreadJobPool… I.e. just do a wait in the runJob of a ThreadPoolJob?
The advantage there would be that I don;t have to do the cleanup, the ThreadPool already does it for me…
In your case just add juce::Thread::sleep(10000)
at the beginning of the runJob function
There is no reason that it shouldn’t work.
and you can even check at the end of the wait if the operation still needs to be done.(allowing cancel)
(A nicer approach would be indeed to use your own WaitableEvent stored in the job with a timeout to allow earlier cancel and not block the job of the whole timeout)
[quote=“jules”]
I don’t think that was ever the case… Timers can get delayed by other activity on the message thread, so they can sometimes fire too late, but I don’t think they’ll ever fire early, at least not by a significant interval.[/quote]
You’re right. I think I confused it with this thread.
[code]void runJob()
{
for (int i = 1000; --i >= 0;)
{
Thread::sleep (10);
if (shouldExit())
return;
}
[/code]
…not elegant, but would avoid messing about with events. I don’t think your code would work properly anyway, as the destructor won’t be called until the job has already finished.
Personally, I’d kick off a timer that would launch a thread to do the work at the right time, rather than having a thread sitting there waiting.
What is “job”? Is it returned by that function? Who owns it? Who created it? Whose responsibility is it to delete it? It’s not obvious to me what’s going on in your code there.
RAII is only difficult to use when you have objects whose ownership is tangled or unclear. And in my humble experience, whenever you have code like that, it’s time for a good re-think!
I rewrote it without the Fifo and just and OwnedArray (with Critical Section), … it’s a lot simpler now, I don’t know why I always want to use lockfree structures Maybe you can have a look at this one and not feel disgusted