Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: third_party/WebKit/Source/wtf/MakeCancellable.h

Issue 2177283005: Add WTF::makeCancellable (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: +self-assign fix, +test, +comment and examples Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 // ScopedFunctionCanceller holds a FunctionCanceller and cancels the target
29 // function on its destruction.
haraken 2016/07/29 14:02:52 Are you assuming that normal developers use both F
tzik 2016/07/29 16:49:13 Since all existing implementations of custom cance
haraken 2016/07/29 19:18:39 I'm a bit confused. Then what's the point of split
tzik 2016/07/29 21:10:36 That's to make the auto cancel opt-in per comments
30 // Example:
31 // void Foo() {}
32 //
33 // std::unique_ptr<Closure> f = bind(&Foo);
34 // RefPtr<FunctionCanceller> canceller;
35 // std::tie(g, canceller) = makeCancellable(std::move(f));
haraken 2016/07/29 14:02:52 Nit: I'd prefer passing the canceller parameter as
tzik 2016/07/29 16:49:13 Updated. I want to avoid using the output paramet
36 //
37 // {
38 // ScopedFunctionCanceller scopedCanceller(canceller);
39 // // Scope out of |scopedCanceller| cancels Foo invocation.
40 // // (*g)(); will be no-op.
41 // }
42 //
43 // ScopedFunctionCanceller scopedCanceller(canceller);
44 //
45 // // Manual cancellation is also available. This cancels the invocation
46 // // of Foo too.
47 // scopedCanceller.cancel();
48 //
49 // // detach() unassociates the FunctionCanceller instance without cancelling
50 // // it. After detach() call, the destructor nor cancel() no longer cancels
51 // // the invocation of Foo.
52 // scopedCanceller.detach();
53 //
54 class WTF_EXPORT ScopedFunctionCanceller {
haraken 2016/07/29 14:02:52 Can this be DISALLOW_ALLOCATION?
tzik 2016/07/29 16:49:13 Done.
55 public:
56 ScopedFunctionCanceller();
57 explicit ScopedFunctionCanceller(PassRefPtr<FunctionCanceller>);
58
59 ScopedFunctionCanceller(ScopedFunctionCanceller&&);
60 ScopedFunctionCanceller& operator=(ScopedFunctionCanceller&&);
61 ScopedFunctionCanceller(const ScopedFunctionCanceller&) = delete;
62 ScopedFunctionCanceller& operator=(const ScopedFunctionCanceller&) = delete;
63
64 ~ScopedFunctionCanceller();
65 void detach();
66 void cancel();
67
68 private:
69 RefPtr<FunctionCanceller> m_canceller;
70 };
71
72 namespace internal {
73
74 template <typename... Params>
75 class FunctionCancellerImpl final : public FunctionCanceller {
76 public:
77 FunctionCancellerImpl(std::unique_ptr<Function<void(Params...)>> function)
78 : m_function(std::move(function))
79 {
80 DCHECK(m_function);
81 }
82
83 void runUnlessCancelled(const ScopedFunctionCanceller&, Params... params)
84 {
85 if (m_function)
86 (*m_function)(std::forward<Params>(params)...);
87 }
88
89 void cancel() override
90 {
91 m_function = nullptr;
92 }
93
94 private:
95 ~FunctionCancellerImpl() override = default;
96
97 std::unique_ptr<WTF::Function<void(Params...)>> m_function;
98
99 DISALLOW_COPY_AND_ASSIGN(FunctionCancellerImpl);
100 };
101
102 } // namespace internal
103
104 // makeCancellable wraps a WTF::Function to make cancellable function.
105 // This function returns a tuple of a WTF::Function, and a FunctionCanceller.
106 // An invocation of the resulting function is relayed to the original function
107 // if the FunctionCanceller::cancel() is not called.
108 //
109 // Example:
110 // void foo() {}
111 // std::unique_ptr<Function<void()>> function = WTF::bind(&foo);
112 //
113 // std::unique_ptr<Function<void()>> wrappedFunction;
114 // RefPtr<FunctionCanceller> canceller;
115 // std::tie(wrappedFunction, canceller) = makeCancellable(std::move(function)) ;
116 //
117 // (*wrappedFunction)(); // Not cancelled. foo() is called.
118 // canceller->cancel();
119 // (*wrappedFunction)(); // Cancelled. foo() is not called.
120 //
121 template <typename... Params>
122 std::tuple<std::unique_ptr<Function<void(Params...)>>, PassRefPtr<FunctionCancel ler>>
123 makeCancellable(std::unique_ptr<Function<void(Params...)>> function)
124 {
125 using Canceller = internal::FunctionCancellerImpl<Params...>;
126 RefPtr<Canceller> canceller = adoptRef(new Canceller(std::move(function)));
127
128 // Keep a ScopedFunctionCanceller instance in |wrappedFunction| below, so
129 // that the destruction of |wrappedFunction| implies the destruction of
130 // |function|. This is needed to avoid a circular strong reference among a
131 // bound parameter, Function, and FunctionCanceller.
132 //
133 // E.g.:
134 // struct Foo : GarbageCollectedFinalized<Foo> {
135 // RefPtr<FunctionCanceller> m_canceller;
136 // void bar();
137 // };
138 //
139 // Foo* foo = new Foo;
140 // std::unique_ptr<Closure> g;
141 // std::tie(g, foo->m_canceller) =
142 // makeCancellable(bind(&Foo::bar, wrapPersistent(foo)));
143 //
144 // // Destruction of the resulting Function implies the destruction of
145 // // the original function via ScopedFunctionCanceller below, that
146 // // resolves a circular strong reference:
147 // // foo -> m_canceller -> m_function -> foo
148 // g = nullptr;
149 std::unique_ptr<Function<void(Params...)>> wrappedFunction =
150 bind(&Canceller::runUnlessCancelled, canceller, ScopedFunctionCanceller( canceller));
151 return std::make_tuple(std::move(wrappedFunction), canceller.release());
152 }
153
154 } // namespace WTF
155
156 #endif // WTF_MakeCancellable_h
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/wtf/MakeCancellable.cpp » ('j') | third_party/WebKit/Source/wtf/MakeCancellable.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698