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 26namespace OHOS::Ace { 27 28using std::chrono_literals::operator""s; 29using std::chrono_literals::operator""ms; 30 31using TaskThread = uint32_t; 32constexpr TaskThread PLATFORM_TASK = 0; 33constexpr TaskThread MAIN_TASK = 1; 34constexpr TaskThread BACKGROUND_TASK = 1 << 1; 35constexpr TaskThread UNDEFINED_TASK = 1 << 2; 36 37template<class> 38class CancelableCallback; 39 40template<class... V> 41class CancelableCallback<void(V...)> final { 42public: 43 using FunctionType = std::function<void(V...)>; 44 45 CancelableCallback() = default; 46 explicit CancelableCallback(const FunctionType& callback) 47 : impl_(callback ? Referenced::MakeRefPtr<Callback>(callback) : nullptr) 48 {} 49 explicit CancelableCallback(FunctionType&& callback) 50 : impl_(callback ? Referenced::MakeRefPtr<Callback>(std::move(callback)) : nullptr) 51 {} 52 CancelableCallback(const FunctionType& callback, TaskThread taskThread) 53 : impl_(callback ? Referenced::MakeRefPtr<Callback>(callback) : nullptr), taskThread_(taskThread) 54 {} 55 CancelableCallback(FunctionType&& callback, TaskThread taskThread) 56 : impl_(callback ? Referenced::MakeRefPtr<Callback>(std::move(callback)) : nullptr), taskThread_(taskThread) 57 {} 58 ~CancelableCallback() = default; 59 60 void SetTaskThreadType(TaskThread taskThread) {} 61 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 77private: 78 enum : int32_t { 79 READY, 80 CANCELED, 81 RUNNING, 82 COMPLETED, 83 }; 84 85 struct Callback final : public Referenced { 86 explicit Callback(const FunctionType& callback) : callback_(callback) {} 87 explicit Callback(FunctionType&& callback) : callback_(std::move(callback)) {} 88 ~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 107template<class... V> 108void 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 117template<class... V> 118void 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 127template<class... V> 128bool 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 155template<class... V> 156bool 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 180template<class... V> 181void 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