Issues creating multiple timers with CFRunLoopTimerCreate

71 views Asked by At

I'm trying to create multiple periodic timers for my macOS launch daemon. I've written the following class to deal with the timer object:

struct MyTimer
{

MyTimer()
{
}

~MyTimer()
{
    stopTimer();
}


bool setTimer(size_t nmsPeriod, //Period in milliseconds
              void (*pfn)(void) //Function to call when timer fires
             )
{
    stopTimer();

    CFTimeInterval fInterval = ((CFTimeInterval)nmsPeriod) / 1000.0;

    CFRunLoopTimerContext ctx = {};
    ctx.info = this;

    _pfnCallback = pfn;

    _refTmr = CFRunLoopTimerCreate(kCFAllocatorDefault,
                                   CFAbsoluteTimeGetCurrent() + fInterval,
                                   fInterval,
                                   0, 0,
                                   _callbackTmr,
                                   &ctx);

    if(!_refTmr)
        return false;

    CFRunLoopAddTimer(CFRunLoopGetCurrent(), _refTmr, kCFRunLoopCommonModes);

    return true;
}

void stopTimer()
{
    if(_refTmr)
    {
        CFRunLoopTimerInvalidate(_refTmr);
            
        CFRelease(_refTmr);
            
        _refTmr = NULL;
    }
}


protected:
    static void _callbackTmr(CFRunLoopTimerRef timer, void *info)
    {
        MyTimer* pThis = (MyTimer*)info;
        pThis->_pfnCallback();
    }


private:

    CFRunLoopTimerRef _refTmr = NULL;
    void (*_pfnCallback)(void) = NULL;
}

Both timer classes are defined on the global scale for the daemon:

MyTimer gTmr1;
MyTimer gTmr2;

And this is how I initiate those timers when the daemon launches:

//Set 1st timer 2 minutes from now
gTmr1.setTimer(2 * 60 * 1000, callback1);

//Set 2nd timer 300 seconds from now
gTmr2.setTimer(300 * 1000, callback2);

//And then reset the 2nd timer 2 seconds from now
gTmr2.setTimer(2 * 1000, callback2);

// ...

//Enter the run-loop...
CFRunLoopRun();

What happens is that callback2 never fires, and only callback1:

static void callback1(void)
{
   log("Callback 1 fired");
}

static void callback2(void)
{
   log("Callback 2 fired");
}

So what am I doing wrong?

0

There are 0 answers