Chromium Code Reviews| 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 |