У меня есть 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();
}
}