OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef WTF_MakeCancellable_h | |
6 #define WTF_MakeCancellable_h | |
7 | |
8 #include "base/logging.h" | |
9 #include "wtf/Functional.h" | |
10 #include "wtf/RefCounted.h" | |
11 #include "wtf/WTFExport.h" | |
12 #include <memory> | |
13 | |
14 namespace WTF { | |
15 | |
16 class FunctionCanceller; | |
17 | |
18 namespace internal { | |
19 | |
20 class WTF_EXPORT FunctionCancellerImplBase : public RefCounted<FunctionCanceller ImplBase> { | |
haraken
2016/07/27 11:18:04
Do we need WTF_EXPORT? It looks strange to export
tzik
2016/07/27 13:56:53
Yes, we need it to expose the ctor and dtor to Fun
| |
21 public: | |
22 virtual void cancel() = 0; | |
23 | |
24 protected: | |
25 FunctionCancellerImplBase(); | |
26 virtual ~FunctionCancellerImplBase(); | |
27 friend RefCounted<FunctionCancellerImplBase>; | |
28 | |
29 DISALLOW_COPY_AND_ASSIGN(FunctionCancellerImplBase); | |
30 }; | |
31 | |
32 template <typename... Params> | |
33 class FunctionCancellerImpl final : public FunctionCancellerImplBase { | |
34 public: | |
35 FunctionCancellerImpl(std::unique_ptr<Function<void(Params...)>> function) | |
36 : m_function(std::move(function)) | |
37 { | |
38 DCHECK(m_function); | |
39 } | |
40 | |
41 void runUnlessCancelled(const FunctionCanceller&, Params... params) | |
42 { | |
43 if (m_function) | |
44 (*m_function)(std::forward<Params>(params)...); | |
45 } | |
46 | |
47 void cancel() override | |
48 { | |
49 m_function = nullptr; | |
50 } | |
51 | |
52 private: | |
53 ~FunctionCancellerImpl() override = default; | |
54 | |
55 std::unique_ptr<WTF::Function<void(Params...)>> m_function; | |
56 | |
57 DISALLOW_COPY_AND_ASSIGN(FunctionCancellerImpl); | |
58 }; | |
59 | |
60 } // namespace internal | |
61 | |
62 class WTF_EXPORT FunctionCanceller { | |
63 public: | |
64 FunctionCanceller(); | |
65 explicit FunctionCanceller(PassRefPtr<internal::FunctionCancellerImplBase> c ancellation); | |
66 | |
67 FunctionCanceller(FunctionCanceller&&); | |
68 FunctionCanceller& operator=(FunctionCanceller&&); | |
69 FunctionCanceller(const FunctionCanceller&) = delete; | |
70 FunctionCanceller& operator=(const FunctionCanceller&) = delete; | |
71 | |
72 ~FunctionCanceller(); | |
73 void detach(); | |
74 void cancel(); | |
75 | |
76 private: | |
77 RefPtr<internal::FunctionCancellerImplBase> m_cancellation; | |
78 }; | |
79 | |
80 // makeCancellable wraps a WTF::Function to make cancellable function. | |
81 // This function returns a tuple of a WTF::Function, and a FunctionCanceller. | |
82 // An invocation of the resulting function is relayed to the original function | |
83 // unless the FunctionCanceller is alive and its cancel() is not called. | |
haraken
2016/07/27 11:18:04
unless => if ?
tzik
2016/07/27 13:56:52
Done.
| |
84 // | |
85 // Example: | |
86 // void foo() {} | |
87 // std::unique_ptr<Function<void()>> function = WTF::bind(&foo); | |
88 // | |
89 // std::unique_ptr<Function<void()>> wrappedFunction; | |
90 // FunctionCanceller canceller; | |
91 // std::tie(wrappedFunction, canceller) = makeCancellable(std::move(function)) ; | |
haraken
2016/07/27 11:18:04
Instead of returning a pair of WTF::Function and F
tzik
2016/07/27 13:56:53
Hmm, since the Function will be posted to a messag
haraken
2016/07/27 14:05:46
Do you mean that the following pattern is complica
| |
92 // | |
93 // (*wrappedFunction)(); // Not cancelled. foo() is called. | |
94 // canceller.cancel(); | |
95 // (*wrappedFunction)(); // Cancelled. foo() is not called. | |
96 // | |
97 // | |
98 // std::tie(wrappedFunction, canceller) = makeCancellable(bind(&foo)); | |
99 // { | |
100 // // FunctionCanceller is movable. |wrappedFunction| will be cancelled | |
101 // // by anotherCanceller.cancel() rather than canceller.cancel(). | |
102 // FunctionCanceller anotherCanceller = std::move(canceller); | |
103 // | |
104 // // Destructor of FunctionCanceller implies cancel(), unless detach() is | |
105 // // called. | |
106 // } | |
107 // | |
108 template <typename... Params> | |
109 std::tuple<std::unique_ptr<Function<void(Params...)>>, FunctionCanceller> | |
110 makeCancellable(std::unique_ptr<Function<void(Params...)>> function) | |
111 { | |
112 using Impl = internal::FunctionCancellerImpl<Params...>; | |
113 RefPtr<Impl> impl = adoptRef(new Impl(std::move(function))); | |
114 // Keep a FunctionCanceller instance in the wrappedFunction itself, so that the target function | |
115 // is destroyed when the Function instance is destroyed. | |
116 std::unique_ptr<Function<void(Params...)>> wrappedFunction = bind(&Impl::run UnlessCancelled, impl, FunctionCanceller(impl)); | |
117 return std::make_tuple(std::move(wrappedFunction), FunctionCanceller(std::mo ve(impl))); | |
118 } | |
119 | |
120 } // namespace WTF | |
121 | |
122 #endif // WTF_MakeCancellable_h | |
OLD | NEW |