Index: src/shared/EventWithSetter.h |
diff --git a/src/shared/EventWithSetter.h b/src/shared/EventWithSetter.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b5c12af10049d0a7288a841b9c4151c778cfb1c5 |
--- /dev/null |
+++ b/src/shared/EventWithSetter.h |
@@ -0,0 +1,100 @@ |
+#pragma once |
+/* |
+* This file is part of Adblock Plus <https://adblockplus.org/>, |
+* Copyright (C) 2006-2016 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 "AutoHandle.h" |
+#include <cstdint> |
+#include <memory> |
+ |
+/// Wrapper around unnamed manual event windows object. |
+class Event { |
+public: |
+ enum { |
+ InfiniteTimeout = 0xFFFFFFFF |
+ }; |
+ /// Creates manual event with nonsignaled initial state. |
+ Event(); |
+ ~Event(); |
+ void Set(); |
+ void Reset(); |
+ bool operator!() const { |
+ return m_handle == nullptr; |
+ } |
+ bool Wait(int32_t timeoutMsec = InfiniteTimeout); |
+private: |
+ Event(const Event&); |
+ void operator=(const Event&); |
+private: |
+ HANDLE m_handle; |
+}; |
+ |
+/// This class is a temporary replacement of std::promise/std::future. |
+/// |
+/// Before scheduling a task to a worker thread, the caller creates |
+/// `EventWithSetter` and obtains `EventWithSetter::Setter`. The task at the |
+/// end should call `EventWithSetter::Setter::Set` to notify the caller about |
+/// finishing. |
+/// If the the task is not finished because it has been canceled or it has |
+/// thrown an exception then the `EventWithSetter::Wait` returns `false`. |
+/// Example: |
+/// EventWithSetter event; |
+/// { // this scope is important because without it if `doWork()` throws |
+/// // `setter` won't be destroyed and the caller will wait forever. |
+/// auto setter = event.CreateSetter(); |
+/// dispatchTask([setter]{ |
+/// doWork(); |
+/// setter->Set(); |
+/// }); |
+/// } |
+/// if (event.Wait()) onSuccess(); |
+/// else onFail(); |
+class EventWithSetter |
+{ |
+public: |
+ class Setter; |
+private: |
+ struct Data |
+ { |
+ Data() : isSetCalled(false), isSetterCreated(false) |
+ {} |
+ Event event; |
+ std::weak_ptr<Setter> eventSetter; |
+ bool isSetCalled; |
+ bool isSetterCreated; |
+ }; |
+ typedef std::shared_ptr<Data> DataPtr; |
+public: |
+ class Setter |
+ { |
+ public: |
+ Setter(const DataPtr& data); |
+ ~Setter(); |
+ void Set(); |
+ private: |
+ Setter(const Setter&); |
+ void operator=(const Setter&); |
+ private: |
+ DataPtr m_data; |
+ }; |
+ EventWithSetter(); |
+ std::shared_ptr<Setter> CreateSetter(); |
+ bool Wait(int32_t timeoutMsec = Event::InfiniteTimeout); |
+private: |
+ EventWithSetter(const EventWithSetter&); |
+ void operator=(const EventWithSetter&); |
+private: |
+ DataPtr m_data; |
+}; |