blackstar

V1

2022/10/09阅读:58主题:默认主题

Windows API 实现高精度定时器

背景

AES67标准草案中,RTP发送端需要对指定采样率下的按照包时间间隔发送RTP音频包,一般的定时器的间隔抖动无法满足需求;需要实现高精度的定时器

关键 Win32 API

  • CreateWaitableTimerExW
  HANDLE CreateWaitableTimerExW(
  [in, optional] LPSECURITY_ATTRIBUTES lpTimerAttributes,
  [in, optional] LPCWSTR               lpTimerName,
  [in]           DWORD                 dwFlags,
  [in]           DWORD                 dwDesiredAccess
)
;

| 功能:创建或打开一个可等待定时器对象并返回指向该对象的句柄

  • SetWaitableTimer
  BOOL SetWaitableTimer(
  [in]           HANDLE              hTimer,
  [in]           const LARGE_INTEGER *lpDueTime,
  [in]           LONG                lPeriod,
  [in, optional] PTIMERAPCROUTINE    pfnCompletionRoutine,
  [in, optional] LPVOID              lpArgToCompletionRoutine,
  [in]           BOOL                fResume
)
;

| 功能:激活由CreateWaitableTimerExW创建的定时器对象。当前延迟时间达到,定时器被触发并且现场调用定时器预先设置的pfnCompletionRoutine

关键代码实现

#include <Windows.h>
#include <string>
#include "thread_pool.h"   // no show code of implement


class HighTimerImpl
{

public:
    HighTimerImpl()
        : _duration(std::chrono::milliseconds(0))
        , _callback(nullptr)
        , _handle(nullptr)
        , _running(false)
    {
    }

    ~HighTimerImpl()
    {
        Stop();
    }

    void AddTimerTask(std::function<void()> callback, const std::chrono::milliseconds& duration)
    
{
        _duration = duration;
        _callback = callback;

        Start();
    }

    void Start()
    
{
        if (!_running.load()) {
            _thrd.Startup();
            _thrd.Commit([this]() {OnTimer(); });
        }
    }

    void Stop()
    
{
        _running.store(false);
        _thrd.Shutdown();

        if (_handle) {
            ::CancelWaitableTimer(_handle);
            ::CloseHandle(_handle);
            _handle = nullptr;
        }
    }

private:

    void OnTimer()
    
{
        _running.store(true);

        LARGE_INTEGER li;
        li.QuadPart = 0;

        _handle = CreateWaitableTimerExW(NULLNULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
        if (_handle == NULL) {
            throw;
        }
        if (!::SetWaitableTimer(_handle, &li,static_cast<long>(_duration.count()), NULLNULL0)) {
            throw;
        }
        while (true) {
            ::WaitForSingleObject(_handle, INFINITE);
            if (!_running.load()) {
                return;
            }

            if (_callback) {
                _callback();
            }

        }
    }

private:
    std::chrono::milliseconds _duration;
    std::function<void()>     _callback;

    HANDLE                    _handle;

    ThreadPool                _thrd;
    std::atomic_bool          _running;

对比其他定时器测试

  • 正常精度定时器测试

  • 高精度定时器测试

对比测试,高精度定时器抖动在1ms范围内;但是正常精度定时器抖动范围已经达到6ms

分类:

后端

标签:

C++

作者介绍

blackstar
V1

一个常年混迹于摸鱼网站的码农