2017-06-01 127 views
0

我想在OSX上每N毫秒(理想情况下为1)获得一个回调。我已经成立了一个CFRunLoop,然后添加一个定时器,像这样:OSX上的定时器回调

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毫秒不是短。

回答

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上做...