Значения старения в очереди: Лучшее использование таймеров Windows? - PullRequest
0 голосов
/ 30 апреля 2020

У меня есть std :: set, который содержит уникальные значения. У меня есть std :: queue, которая содержит те же значения, чтобы устаревать значения в std :: set.

Я хотел бы использовать таймер, чтобы определить, когда извлекать значение из очереди, а затем удалить его из набора. Таймер создается / запускается каждый раз, когда данные добавляются в пустой набор / очередь. Если данные добавляются в непустой набор / очередь, таймер не изменяется. Таймер будет запускать каждые X миллисекунд для выполнения функции. Функция извлекает значение из очереди, а затем удаляет это значение из набора. Если набор / очередь сейчас пуст, таймер остановится. Если набор / очередь не пустые, в таймер не вносятся никакие изменения.

Эта программа работает в Windows 10.

Имеет ли этот способ смысл? Есть ли лучший / более эффективный / более простой способ устаревания данных?

Я прочитал документы по использованию очередей таймера, поэтому я вижу, как создаются и удаляются очередь и таймеры. То, что я не вижу, является рекомендацией для запуска / остановки таймеров. Должен ли я создавать новый TimerQueueTimer для однократного ожидания X миллисекунд, запустить fun c, а затем создать новый 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();
    }
}

1 Ответ

0 голосов
/ 30 апреля 2020

Исследования показывают, что CreateTimerQueue / CreateTimerQueueTimer, возможно, не путь к go. Использование ThreadpoolTimer

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...