• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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