OSX上的常规计时器回调

时间:2017-06-01 14:11:30

标签: macos timer scheduling

我试图在OSX上每N毫秒(理想情况下为1)获得一次回调。我已经设置了CFRunLoop然后添加了一个计时器,如下所示:

const double period = 0.001;

CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();

CFRunLoopTimerContext context;
std::memset(&context, 0, sizeof(context));
context.info = ...;

CFRunLoopTimerRef timerRef = CFRunLoopTimerCreate(kCFAllocatorDefault, now + period, period, 0, 0, RunLoopTimerCallBack, &context);

// Add it to the loop.
CFRunLoopAddTimer(/* my run loop reference */, timerRef, kCFRunLoopDefaultMode);

它似乎有效 - 我的RunLoopTimerCallback()大约每毫秒被调用一次。除非它没有。 documentation for CFRunLoopTimerCreate说:

  

如果存在实现原因,则可以通过定时器稍微调整间隔的精确精度(最多亚毫秒)。

所以我希望它或多或少有效,但实际上我在最多8毫秒的回调之间会出现延迟:

delay graph

我已经尝试setting the run loop thread to real-time priority,但它没有任何区别。有谁知道为什么我会得到这些延误?我意识到这很难推动操作系统,也许这是一些调度问题,但仍然...... 1毫秒

1 个答案:

答案 0 :(得分:0)

实际上,我是个白痴。设置实时线程优先级会产生巨大的差异。结果如下:

millisecond!

以下是我使用的代码:

#include <mach/mach_time.h>
#include <mach/thread_policy.h>

#include <iostream> 
using namespace std;

void SetPriorityRealtime()
{
    mach_timebase_info_data_t timebase;
    kern_return_t kr = mach_timebase_info(&timebase);
    if (kr != KERN_SUCCESS)
    {
        cerr << "Warning: Couldn't get timebase." << endl;
        return;
    }

    // The number of nanoseconds per tick is: 
    cerr << timebase.numer << " / " << timebase.denom << endl;

    // Set the thread priority.
    thread_time_constraint_policy ttcpolicy;
    thread_port_t threadport = pthread_mach_thread_np(pthread_self());

    // In ticks. Therefore to convert nanoseconds to ticks multiply by (timebase.denom / timebase.numer).
    ttcpolicy.period = 500 * 1000 * timebase.denom / timebase.numer; // Period over which we demand scheduling.
    ttcpolicy.computation = 100 * 1000 * timebase.denom / timebase.numer; // Minimum time in a period where we must be running.
    ttcpolicy.constraint = 100 * 1000 * timebase.denom / timebase.numer; // Maximum time between start and end of our computation in the period.
    ttcpolicy.preemptible = FALSE;

    kr = thread_policy_set(threadport, THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&ttcpolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT);
    if (kr != KERN_SUCCESS)
    {
        cerr << "Warning: Couldn't set thread policy: " << kr << endl;
        return;
    }
}

说实话,我还不完全确定thread_time_constraint_policy成员如何影响事物。但至少这表明它是可能的。现在在Windows上做...