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 using std::chrono_literals::operator""s;
29 using std::chrono_literals::operator""ms;
30
31 using TaskThread = uint32_t;
32 constexpr TaskThread PLATFORM_TASK = 0;
33 constexpr TaskThread MAIN_TASK = 1;
34 constexpr TaskThread BACKGROUND_TASK = 1 << 1;
35 constexpr TaskThread UNDEFINED_TASK = 1 << 2;
36
37 template<class>
38 class CancelableCallback;
39
40 template<class... V>
41 class CancelableCallback<void(V...)> final {
42 public:
43 using FunctionType = std::function<void(V...)>;
44
45 CancelableCallback() = default;
CancelableCallback(const FunctionType & callback)46 explicit CancelableCallback(const FunctionType& callback)
47 : impl_(callback ? Referenced::MakeRefPtr<Callback>(callback) : nullptr)
48 {}
CancelableCallback(FunctionType && callback)49 explicit CancelableCallback(FunctionType&& callback)
50 : impl_(callback ? Referenced::MakeRefPtr<Callback>(std::move(callback)) : nullptr)
51 {}
CancelableCallback(const FunctionType & callback,TaskThread taskThread)52 CancelableCallback(const FunctionType& callback, TaskThread taskThread)
53 : impl_(callback ? Referenced::MakeRefPtr<Callback>(callback) : nullptr), taskThread_(taskThread)
54 {}
CancelableCallback(FunctionType && callback,TaskThread taskThread)55 CancelableCallback(FunctionType&& callback, TaskThread taskThread)
56 : impl_(callback ? Referenced::MakeRefPtr<Callback>(std::move(callback)) : nullptr), taskThread_(taskThread)
57 {}
58 ~CancelableCallback() = default;
59
SetTaskThreadType(TaskThread taskThread)60 void SetTaskThreadType(TaskThread taskThread) {}
61
GetTaskThreadType()62 TaskThread GetTaskThreadType() const
63 {
64 return MAIN_TASK;
65 }
66
67 void Reset(const FunctionType& callback, bool needCancel = true, bool waitUntilCompleted = false);
68 void Reset(FunctionType&& callback, bool needCancel = true, bool waitUntilCompleted = false);
69 bool WaitUntilComplete(std::chrono::milliseconds timeoutMs = 0ms);
70 bool Cancel(bool waitUntilCompleted = false);
71 void operator()(V&&... values) const;
72 operator bool() const
73 {
74 return impl_ && impl_->callback_;
75 }
76
77 private:
78 enum : int32_t {
79 READY,
80 CANCELED,
81 RUNNING,
82 COMPLETED,
83 };
84
85 struct Callback final : public Referenced {
Callbackfinal86 explicit Callback(const FunctionType& callback) : callback_(callback) {}
Callbackfinal87 explicit Callback(FunctionType&& callback) : callback_(std::move(callback)) {}
~Callbackfinal88 ~Callback() override
89 {
90 int32_t status = status_.load(std::memory_order_relaxed);
91 ACE_DCHECK(status != RUNNING);
92 if (status == READY) {
93 promise_.set_value(CANCELED);
94 }
95 }
96
97 FunctionType callback_;
98 std::atomic<int32_t> status_ { READY };
99 std::promise<int32_t> promise_;
100 std::shared_future<int32_t> future_ { promise_.get_future() };
101 };
102
103 RefPtr<Callback> impl_;
104 TaskThread taskThread_ = MAIN_TASK;
105 };
106
107 template<class... V>
Reset(const CancelableCallback<void (V...)>::FunctionType & callback,bool needCancel,bool waitUntilCompleted)108 void CancelableCallback<void(V...)>::Reset(
109 const CancelableCallback<void(V...)>::FunctionType& callback, bool needCancel, bool waitUntilCompleted)
110 {
111 if (needCancel) {
112 Cancel(waitUntilCompleted);
113 }
114 impl_ = callback ? Referenced::MakeRefPtr<Callback>(callback) : nullptr;
115 }
116
117 template<class... V>
Reset(CancelableCallback<void (V...)>::FunctionType && callback,bool needCancel,bool waitUntilCompleted)118 void CancelableCallback<void(V...)>::Reset(
119 CancelableCallback<void(V...)>::FunctionType&& callback, bool needCancel, bool waitUntilCompleted)
120 {
121 if (needCancel) {
122 Cancel(waitUntilCompleted);
123 }
124 impl_ = callback ? Referenced::MakeRefPtr<Callback>(std::move(callback)) : nullptr;
125 }
126
127 template<class... V>
WaitUntilComplete(std::chrono::milliseconds timeoutMs)128 bool CancelableCallback<void(V...)>::WaitUntilComplete(std::chrono::milliseconds timeoutMs)
129 {
130 RefPtr<Callback> impl(std::move(impl_));
131 if (!impl) {
132 return false;
133 }
134
135 switch (impl->status_.load(std::memory_order_relaxed)) {
136 case READY:
137 case RUNNING: {
138 std::shared_future<int32_t> future(impl->future_);
139 if (timeoutMs != 0ms && std::future_status::timeout == future.wait_for(timeoutMs)) {
140 CancelableCallback avatar(*this);
141 avatar.impl_ = impl;
142 avatar.Cancel(true);
143 }
144 impl.Reset();
145 return future.get() == COMPLETED;
146 }
147 case COMPLETED:
148 return true;
149 case CANCELED:
150 default:
151 return false;
152 }
153 }
154
155 template<class... V>
Cancel(bool waitUntilCompleted)156 bool CancelableCallback<void(V...)>::Cancel(bool waitUntilCompleted)
157 {
158 RefPtr<Callback> impl(std::move(impl_));
159 if (!impl) {
160 return true;
161 }
162
163 int32_t status = READY;
164 if (impl->status_.compare_exchange_strong(status, CANCELED, std::memory_order_relaxed)) {
165 impl->promise_.set_value(CANCELED);
166 return true;
167 } else if (status == CANCELED) {
168 return true;
169 }
170
171 if (waitUntilCompleted && status == RUNNING) {
172 std::shared_future<int32_t> future(impl->future_);
173 impl.Reset();
174 status = future.get();
175 ACE_DCHECK(status == COMPLETED);
176 }
177 return false;
178 }
179
180 template<class... V>
operator()181 void CancelableCallback<void(V...)>::operator()(V&&... values) const
182 {
183 RefPtr<Callback> impl(std::move(impl_));
184 if (!impl) {
185 return;
186 }
187
188 int32_t status = READY;
189 if (impl->status_.compare_exchange_strong(status, RUNNING, std::memory_order_relaxed)) {
190 impl->callback_(std::forward<V>(values)...);
191 impl->status_.store(COMPLETED);
192 impl->promise_.set_value(COMPLETED);
193 }
194 }
195
196 } // namespace OHOS::Ace
197
198 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_THREAD_CANCELABEL_CALLBACK_H
199