首页 > 解决方案 > 队列中的老化值:Windows 计时器的最佳使用?

问题描述

我有一个包含唯一值的 std::set。我有一个保存相同值的 std::queue,以便对 std::set 中的值进行老化。

我想使用计时器来确定何时从队列中弹出一个值,然后从集合中删除该值。每次将数据添加到空集/队列时,都会创建/启动计时器。如果将数据添加到非空集合/队列中,则不会对计时器进行任何更改。计时器将每 X 毫秒触发一次以执行一个函数。该函数将从队列中弹出一个值,然后从集合中删除该值。如果集合/队列现在为空,则计时器将停止。如果 set/queue 不为空,则不更改计时器。

该程序在 Windows 10 中运行。

这种方式有意义吗?是否有更好/更有效/更简单的方法来老化数据?

我已阅读有关 Using Timer Queues 的文档,因此我了解了如何创建和销毁队列和计时器。我没有看到启动/停止计时器的建议。如果集合/队列不为空,我是否应该创建一个新的 TimerQueueTimer 以等待 X 毫秒,运行 func 然后创建一个新的 TimerQueueTimer?我是否应该创建一个 TimerQueueTimer 来定期运行 X 毫秒,但在集合/队列为空时将其删除?

我应该使用第三种技术吗?

这是我的示例代码。

using unsignedIntSet = std::set<std::uint32_t>;
using unsignedIntQ = std::queue<std::uint32_t>;
unsignedIntQ agingQ;
unsignedIntSet agingSet;

HANDLE gDoneEvent = NULL;
HANDLE hTimer = NULL;
HANDLE hTimerQueue = NULL;

VOID CALLBACK ageTimer(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{

    if (!agingQ.empty())
    {
        auto c = agingQ.front();
        agingSet.erase(c);
        agingQ.pop();

        if (!agingQ.empty())
        {
            // rerun CreateTimerQueueTimer() here?
        }
    }

    SetEvent(gDoneEvent);
}

int createTimerForAgingQ()
{
    // create timer if it doesn't already exist
    if (gDoneEvent == NULL)
    {
        gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (gDoneEvent == NULL)
        {
            std::cerr << "CreateEvent() error: " << WSAGetLastError() << std::endl;
            return -1;
        }
        hTimerQueue = CreateTimerQueue();
        if (hTimerQueue == NULL)
        {
            std::cerr << "CreateTimerQueue() error: " << WSAGetLastError() << std::endl;
            return -1;
        }
        if (!CreateTimerQueueTimer(&hTimer, hTimerQueue, (WAITORTIMERCALLBACK)ageTimer, NULL, 500, 0, WT_EXECUTEONLYONCE))
        {
            std::cerr << "CreateTimerQueueTimer() error: " << WSAGetLastError() << std::endl;
            return -1;
        }
    }
}

void addUnique(unsigned char* buffer, int bufferLen)
{
    // hash value
    auto h = hash(buffer, bufferLen);

    // test insert into set
    auto setResult = agingSet.emplace(h);
    if (setResult.second)
    {
        // enqueue into historyQ
        agingQ.emplace(h);

        if (!gDoneEvent) createTimerForAgingQ();
    }
}

标签: windowstimer

解决方案


研究表明 CreateTimerQueue/CreateTimerQueueTimer 可能不是要走的路。 线程池定时器的使用


推荐阅读