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 WTF_EXPORT FunctionCanceller : public RefCounted<FunctionCanceller> { | |
17 public: | |
18 virtual void cancel() = 0; | |
19 | |
20 protected: | |
21 FunctionCanceller(); | |
22 virtual ~FunctionCanceller(); | |
23 friend RefCounted<FunctionCanceller>; | |
24 | |
25 DISALLOW_COPY_AND_ASSIGN(FunctionCanceller); | |
26 }; | |
27 | |
28 class WTF_EXPORT ScopedFunctionCanceller { | |
Yuta Kitamura
2016/07/29 05:58:28
A brief comment about the usage of this class woul
tzik
2016/07/29 13:47:11
Done.
| |
29 public: | |
30 ScopedFunctionCanceller(); | |
31 explicit ScopedFunctionCanceller(PassRefPtr<FunctionCanceller>); | |
32 | |
33 ScopedFunctionCanceller(ScopedFunctionCanceller&&); | |
34 ScopedFunctionCanceller& operator=(ScopedFunctionCanceller&&); | |
35 ScopedFunctionCanceller(const ScopedFunctionCanceller&) = delete; | |
36 ScopedFunctionCanceller& operator=(const ScopedFunctionCanceller&) = delete; | |
37 | |
38 ~ScopedFunctionCanceller(); | |
39 void detach(); | |
40 void cancel(); | |
41 | |
42 private: | |
43 RefPtr<FunctionCanceller> m_canceller; | |
44 }; | |
45 | |
46 namespace internal { | |
47 | |
48 template <typename... Params> | |
49 class FunctionCancellerImpl final : public FunctionCanceller { | |
50 public: | |
51 FunctionCancellerImpl(std::unique_ptr<Function<void(Params...)>> function) | |
52 : m_function(std::move(function)) | |
53 { | |
54 DCHECK(m_function); | |
55 } | |
56 | |
57 void runUnlessCancelled(const ScopedFunctionCanceller&, Params... params) | |
58 { | |
59 if (m_function) | |
60 (*m_function)(std::forward<Params>(params)...); | |
61 } | |
62 | |
63 void cancel() override | |
64 { | |
65 m_function = nullptr; | |
66 } | |
67 | |
68 private: | |
69 ~FunctionCancellerImpl() override = default; | |
70 | |
71 std::unique_ptr<WTF::Function<void(Params...)>> m_function; | |
72 | |
73 DISALLOW_COPY_AND_ASSIGN(FunctionCancellerImpl); | |
74 }; | |
75 | |
76 } // namespace internal | |
77 | |
78 // makeCancellable wraps a WTF::Function to make cancellable function. | |
79 // This function returns a tuple of a WTF::Function, and a FunctionCanceller. | |
80 // An invocation of the resulting function is relayed to the original function | |
81 // if the FunctionCanceller::cancel() is not called. | |
82 // | |
83 // Example: | |
84 // void foo() {} | |
85 // std::unique_ptr<Function<void()>> function = WTF::bind(&foo); | |
86 // | |
87 // std::unique_ptr<Function<void()>> wrappedFunction; | |
88 // RefPtr<FunctionCanceller> canceller; | |
89 // std::tie(wrappedFunction, canceller) = makeCancellable(std::move(function)) ; | |
90 // | |
91 // (*wrappedFunction)(); // Not cancelled. foo() is called. | |
92 // canceller->cancel(); | |
93 // (*wrappedFunction)(); // Cancelled. foo() is not called. | |
94 // | |
95 template <typename... Params> | |
96 std::tuple<std::unique_ptr<Function<void(Params...)>>, PassRefPtr<FunctionCancel ler>> | |
97 makeCancellable(std::unique_ptr<Function<void(Params...)>> function) | |
98 { | |
99 using Canceller = internal::FunctionCancellerImpl<Params...>; | |
100 RefPtr<Canceller> canceller = adoptRef(new Canceller(std::move(function))); | |
101 // Keep a ScopedFunctionCanceller instance in |wrappedFunction|, so that the | |
102 // destruction of |wrappedFunction| implies the destruction of |function|. | |
103 std::unique_ptr<Function<void(Params...)>> wrappedFunction = bind(&Canceller ::runUnlessCancelled, canceller, ScopedFunctionCanceller(canceller)); | |
Yuta Kitamura
2016/07/29 00:57:42
I'm still unsure about the merit of cancelling on
tzik
2016/07/29 05:25:40
My concern is that, without the auto destruction,
Yuta Kitamura
2016/07/29 05:58:28
OK, that makes sense.
Maybe you could add some mo
tzik
2016/07/29 13:47:11
Done.
| |
104 return std::make_tuple(std::move(wrappedFunction), canceller.release()); | |
105 } | |
106 | |
107 } // namespace WTF | |
108 | |
109 #endif // WTF_MakeCancellable_h | |
OLD | NEW |