1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_CANCELABEL_CALLBACK_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_CANCELABEL_CALLBACK_H
18
19 #include <atomic>
20 #include <functional>
21 #include <future>
22
23 #include "base/memory/referenced.h"
24 #include "base/utils/macros.h"
25
26 namespace OHOS::Ace {
27
28 template<class>
29 class CancelableCallback;
30
31 template<class... V>
32 class CancelableCallback<void(V...)> final {
33 public:
34 using FunctionType = std::function<void(V...)>;
35
36 CancelableCallback() = default;
CancelableCallback(const FunctionType & callback)37 explicit CancelableCallback(const FunctionType& callback)
38 : impl_(callback ? Referenced::MakeRefPtr<Callback>(callback) : nullptr)
39 {}
CancelableCallback(FunctionType && callback)40 explicit CancelableCallback(FunctionType&& callback)
41 : impl_(callback ? Referenced::MakeRefPtr<Callback>(std::move(callback)) : nullptr)
42 {}
43 ~CancelableCallback() = default;
44
45 void Reset(const FunctionType& callback, bool needCancel = true, bool waitUntilCompleted = false);
46 void Reset(FunctionType&& callback, bool needCancel = true, bool waitUntilCompleted = false);
47 bool WaitUntilComplete();
48 bool Cancel(bool waitUntilCompleted = false);
49 void operator()(V&&... values) const;
50 operator bool() const
51 {
52 return impl_ && impl_->callback_;
53 }
54
55 private:
56 enum : int32_t {
57 READY,
58 CANCELED,
59 RUNNING,
60 COMPLETED,
61 };
62
63 struct Callback final : public Referenced {
Callbackfinal64 explicit Callback(const FunctionType& callback) : callback_(callback) {}
Callbackfinal65 explicit Callback(FunctionType&& callback) : callback_(std::move(callback)) {}
~Callbackfinal66 ~Callback() override
67 {
68 int32_t status = status_.load(std::memory_order_relaxed);
69 ACE_DCHECK(status != RUNNING);
70 if (status == READY) {
71 promise_.set_value(CANCELED);
72 }
73 }
74
75 FunctionType callback_;
76 std::atomic<int32_t> status_ { READY };
77 std::promise<int32_t> promise_;
78 std::shared_future<int32_t> future_ { promise_.get_future() };
79 };
80
81 RefPtr<Callback> impl_;
82 };
83
84 template<class... V>
Reset(const CancelableCallback<void (V...)>::FunctionType & callback,bool needCancel,bool waitUntilCompleted)85 void CancelableCallback<void(V...)>::Reset(
86 const CancelableCallback<void(V...)>::FunctionType& callback, bool needCancel, bool waitUntilCompleted)
87 {
88 if (needCancel) {
89 Cancel(waitUntilCompleted);
90 }
91 impl_ = callback ? Referenced::MakeRefPtr<Callback>(callback) : nullptr;
92 }
93
94 template<class... V>
Reset(CancelableCallback<void (V...)>::FunctionType && callback,bool needCancel,bool waitUntilCompleted)95 void CancelableCallback<void(V...)>::Reset(
96 CancelableCallback<void(V...)>::FunctionType&& callback, bool needCancel, bool waitUntilCompleted)
97 {
98 if (needCancel) {
99 Cancel(waitUntilCompleted);
100 }
101 impl_ = callback ? Referenced::MakeRefPtr<Callback>(std::move(callback)) : nullptr;
102 }
103
104 template<class... V>
WaitUntilComplete()105 bool CancelableCallback<void(V...)>::WaitUntilComplete()
106 {
107 RefPtr<Callback> impl(std::move(impl_));
108 if (!impl) {
109 return false;
110 }
111
112 switch (impl->status_.load(std::memory_order_relaxed)) {
113 case READY:
114 case RUNNING: {
115 std::shared_future<int32_t> future(impl->future_);
116 impl.Reset();
117 return future.get() == COMPLETED;
118 }
119 case COMPLETED:
120 return true;
121 case CANCELED:
122 default:
123 return false;
124 }
125 }
126
127 template<class... V>
Cancel(bool waitUntilCompleted)128 bool CancelableCallback<void(V...)>::Cancel(bool waitUntilCompleted)
129 {
130 RefPtr<Callback> impl(std::move(impl_));
131 if (!impl) {
132 return true;
133 }
134
135 int32_t status = READY;
136 if (impl->status_.compare_exchange_strong(status, CANCELED, std::memory_order_relaxed)) {
137 impl->promise_.set_value(CANCELED);
138 return true;
139 } else if (status == CANCELED) {
140 return true;
141 }
142
143 if (waitUntilCompleted && status == RUNNING) {
144 std::shared_future<int32_t> future(impl->future_);
145 impl.Reset();
146 status = future.get();
147 ACE_DCHECK(status == COMPLETED);
148 }
149 return false;
150 }
151
152 template<class... V>
operator()153 void CancelableCallback<void(V...)>::operator()(V&&... values) const
154 {
155 RefPtr<Callback> impl(std::move(impl_));
156 if (!impl) {
157 return;
158 }
159
160 int32_t status = READY;
161 if (impl->status_.compare_exchange_strong(status, RUNNING, std::memory_order_relaxed)) {
162 impl->callback_(std::forward<V>(values)...);
163 impl->status_.store(COMPLETED);
164 impl->promise_.set_value(COMPLETED);
165 }
166 }
167
168 } // namespace OHOS::Ace
169
170 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_CANCELABEL_CALLBACK_H
171