Index: src/DefaultTimer.cpp |
diff --git a/src/DefaultTimer.cpp b/src/DefaultTimer.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d4d36e15a3035afe1d7c272b8630a3ed32f1743b |
--- /dev/null |
+++ b/src/DefaultTimer.cpp |
@@ -0,0 +1,83 @@ |
+/* |
+* This file is part of Adblock Plus <https://adblockplus.org/>, |
+* Copyright (C) 2006-2017 eyeo GmbH |
+* |
+* Adblock Plus is free software: you can redistribute it and/or modify |
+* it under the terms of the GNU General Public License version 3 as |
+* published by the Free Software Foundation. |
+* |
+* Adblock Plus is distributed in the hope that it will be useful, |
+* but WITHOUT ANY WARRANTY; without even the implied warranty of |
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+* GNU General Public License for more details. |
+* |
+* You should have received a copy of the GNU General Public License |
+* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
+*/ |
+ |
+#include "DefaultTimer.h" |
+ |
+using AdblockPlus::DefaultTimer; |
+ |
+DefaultTimer::DefaultTimer() |
+ : shouldThreadStop(false) |
+{ |
+ m_thread = std::thread([this] |
+ { |
+ ThreadFunc(); |
+ }); |
+} |
+ |
+DefaultTimer::~DefaultTimer() |
+{ |
+ shouldThreadStop = true; |
+ conditionVariable.notify_one(); |
+ if (m_thread.joinable()) |
+ m_thread.join(); |
+} |
+ |
+void DefaultTimer::SetTimer(const std::chrono::milliseconds& timeout, const TimerCallback& timerCallback) |
+{ |
+ if (!timerCallback) |
+ return; |
+ std::lock_guard<std::mutex> lock(mutex); |
Oleksandr
2017/03/28 10:39:55
If there's already a timer for let's say 1 minute
sergei
2017/03/28 11:06:59
No, `conditionVariable.wait(lock,...` and `conditi
Oleksandr
2017/03/28 11:11:00
Fair enough.
|
+ TimerUnit timer = { std::chrono::steady_clock::now() + timeout, timerCallback }; |
+ timers.push(timer); |
+ conditionVariable.notify_one(); |
+} |
+ |
+void DefaultTimer::ThreadFunc() |
+{ |
+ while (!shouldThreadStop) |
+ { |
+ std::unique_lock<std::mutex> lock(mutex); |
+ if (timers.empty()) |
+ { |
+ conditionVariable.wait(lock, [this]()->bool |
+ { |
+ return shouldThreadStop || !timers.empty(); |
+ }); |
+ } |
+ else |
+ { |
+ conditionVariable.wait_until(lock, timers.top().fireAt); |
+ } |
+ // execute all expired timers and remove them |
+ while (!shouldThreadStop && !timers.empty() && timers.top().fireAt <= std::chrono::steady_clock::now()) |
+ { |
+ auto callback = timers.top().callback; |
+ timers.pop(); |
+ // allow to put new timers while this timer is being processed |
+ lock.unlock(); |
+ try |
+ { |
+ callback(); |
+ } |
+ catch (...) |
+ { |
+ // do nothing, but the thread will be alive. |
+ } |
+ lock.lock(); |
+ } |
+ } |
+} |