1484543d1Sopenharmony_ci/* 2484543d1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3484543d1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4484543d1Sopenharmony_ci * you may not use this file except in compliance with the License. 5484543d1Sopenharmony_ci * You may obtain a copy of the License at 6484543d1Sopenharmony_ci * 7484543d1Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8484543d1Sopenharmony_ci * 9484543d1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10484543d1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11484543d1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12484543d1Sopenharmony_ci * See the License for the specific language governing permissions and 13484543d1Sopenharmony_ci * limitations under the License. 14484543d1Sopenharmony_ci */ 15484543d1Sopenharmony_ci#ifndef FFRT_API_CPP_FUTURE_H 16484543d1Sopenharmony_ci#define FFRT_API_CPP_FUTURE_H 17484543d1Sopenharmony_ci#include <memory> 18484543d1Sopenharmony_ci#include <optional> 19484543d1Sopenharmony_ci#include <chrono> 20484543d1Sopenharmony_ci#include "cpp/condition_variable.h" 21484543d1Sopenharmony_ci#include "thread.h" 22484543d1Sopenharmony_ci 23484543d1Sopenharmony_cinamespace ffrt { 24484543d1Sopenharmony_cistruct non_copyable { 25484543d1Sopenharmony_ciprotected: 26484543d1Sopenharmony_ci non_copyable() = default; 27484543d1Sopenharmony_ci ~non_copyable() = default; 28484543d1Sopenharmony_ci non_copyable(const non_copyable&) = delete; 29484543d1Sopenharmony_ci non_copyable& operator=(const non_copyable&) = delete; 30484543d1Sopenharmony_ci}; 31484543d1Sopenharmony_cienum class future_status { ready, timeout, deferred }; 32484543d1Sopenharmony_ci 33484543d1Sopenharmony_cinamespace detail { 34484543d1Sopenharmony_citemplate <typename Derived> 35484543d1Sopenharmony_cistruct shared_state_base : private non_copyable { 36484543d1Sopenharmony_ci void wait() const noexcept 37484543d1Sopenharmony_ci { 38484543d1Sopenharmony_ci std::unique_lock lk(this->m_mtx); 39484543d1Sopenharmony_ci wait_(lk); 40484543d1Sopenharmony_ci } 41484543d1Sopenharmony_ci 42484543d1Sopenharmony_ci template <typename Rep, typename Period> 43484543d1Sopenharmony_ci future_status wait_for(const std::chrono::duration<Rep, Period>& waitTime) const noexcept 44484543d1Sopenharmony_ci { 45484543d1Sopenharmony_ci std::unique_lock<mutex> lk(m_mtx); 46484543d1Sopenharmony_ci return m_cv.wait_for(lk, waitTime, [this] { return get_derived().has_value(); }) ? future_status::ready : 47484543d1Sopenharmony_ci future_status::timeout; 48484543d1Sopenharmony_ci } 49484543d1Sopenharmony_ci 50484543d1Sopenharmony_ci template <typename Clock, typename Duration> 51484543d1Sopenharmony_ci future_status wait_until(const std::chrono::time_point<Clock, Duration>& tp) const noexcept 52484543d1Sopenharmony_ci { 53484543d1Sopenharmony_ci std::unique_lock<mutex> lk(m_mtx); 54484543d1Sopenharmony_ci return m_cv.wait_until(lk, tp, [this] { return get_derived().has_value(); }) ? future_status::ready : 55484543d1Sopenharmony_ci future_status::timeout; 56484543d1Sopenharmony_ci } 57484543d1Sopenharmony_ci 58484543d1Sopenharmony_ciprotected: 59484543d1Sopenharmony_ci void wait_(std::unique_lock<mutex>& lk) const noexcept 60484543d1Sopenharmony_ci { 61484543d1Sopenharmony_ci m_cv.wait(lk, [this] { return get_derived().has_value(); }); 62484543d1Sopenharmony_ci } 63484543d1Sopenharmony_ci 64484543d1Sopenharmony_ci mutable mutex m_mtx; 65484543d1Sopenharmony_ci mutable condition_variable m_cv; 66484543d1Sopenharmony_ci 67484543d1Sopenharmony_ciprivate: 68484543d1Sopenharmony_ci const Derived& get_derived() const 69484543d1Sopenharmony_ci { 70484543d1Sopenharmony_ci return *static_cast<const Derived*>(this); 71484543d1Sopenharmony_ci } 72484543d1Sopenharmony_ci}; 73484543d1Sopenharmony_ci 74484543d1Sopenharmony_citemplate <typename R> 75484543d1Sopenharmony_cistruct shared_state : public shared_state_base<shared_state<R>> { 76484543d1Sopenharmony_ci void set_value(const R& value) noexcept 77484543d1Sopenharmony_ci { 78484543d1Sopenharmony_ci { 79484543d1Sopenharmony_ci std::unique_lock<mutex> lk(this->m_mtx); 80484543d1Sopenharmony_ci m_res.emplace(value); 81484543d1Sopenharmony_ci } 82484543d1Sopenharmony_ci this->m_cv.notify_all(); 83484543d1Sopenharmony_ci } 84484543d1Sopenharmony_ci 85484543d1Sopenharmony_ci void set_value(R&& value) noexcept 86484543d1Sopenharmony_ci { 87484543d1Sopenharmony_ci { 88484543d1Sopenharmony_ci std::unique_lock<mutex> lk(this->m_mtx); 89484543d1Sopenharmony_ci m_res.emplace(std::move(value)); 90484543d1Sopenharmony_ci } 91484543d1Sopenharmony_ci this->m_cv.notify_all(); 92484543d1Sopenharmony_ci } 93484543d1Sopenharmony_ci 94484543d1Sopenharmony_ci R& get() noexcept 95484543d1Sopenharmony_ci { 96484543d1Sopenharmony_ci std::unique_lock lk(this->m_mtx); 97484543d1Sopenharmony_ci this->wait_(lk); 98484543d1Sopenharmony_ci return m_res.value(); 99484543d1Sopenharmony_ci } 100484543d1Sopenharmony_ci 101484543d1Sopenharmony_ci bool has_value() const noexcept 102484543d1Sopenharmony_ci { 103484543d1Sopenharmony_ci return m_res.has_value(); 104484543d1Sopenharmony_ci } 105484543d1Sopenharmony_ci 106484543d1Sopenharmony_ciprivate: 107484543d1Sopenharmony_ci std::optional<R> m_res; 108484543d1Sopenharmony_ci}; 109484543d1Sopenharmony_ci 110484543d1Sopenharmony_citemplate <> 111484543d1Sopenharmony_cistruct shared_state<void> : public shared_state_base<shared_state<void>> { 112484543d1Sopenharmony_ci void set_value() noexcept 113484543d1Sopenharmony_ci { 114484543d1Sopenharmony_ci { 115484543d1Sopenharmony_ci std::unique_lock<mutex> lk(this->m_mtx); 116484543d1Sopenharmony_ci m_hasValue = true; 117484543d1Sopenharmony_ci } 118484543d1Sopenharmony_ci this->m_cv.notify_all(); 119484543d1Sopenharmony_ci } 120484543d1Sopenharmony_ci 121484543d1Sopenharmony_ci void get() noexcept 122484543d1Sopenharmony_ci { 123484543d1Sopenharmony_ci std::unique_lock lk(this->m_mtx); 124484543d1Sopenharmony_ci this->wait_(lk); 125484543d1Sopenharmony_ci } 126484543d1Sopenharmony_ci 127484543d1Sopenharmony_ci bool has_value() const noexcept 128484543d1Sopenharmony_ci { 129484543d1Sopenharmony_ci return m_hasValue; 130484543d1Sopenharmony_ci } 131484543d1Sopenharmony_ci 132484543d1Sopenharmony_ciprivate: 133484543d1Sopenharmony_ci bool m_hasValue {false}; 134484543d1Sopenharmony_ci}; 135484543d1Sopenharmony_ci}; // namespace detail 136484543d1Sopenharmony_ci 137484543d1Sopenharmony_citemplate <typename R> 138484543d1Sopenharmony_ciclass future : private non_copyable { 139484543d1Sopenharmony_ci template <typename> 140484543d1Sopenharmony_ci friend struct promise; 141484543d1Sopenharmony_ci 142484543d1Sopenharmony_ci template <typename> 143484543d1Sopenharmony_ci friend struct packaged_task; 144484543d1Sopenharmony_ci 145484543d1Sopenharmony_cipublic: 146484543d1Sopenharmony_ci explicit future(const std::shared_ptr<detail::shared_state<R>>& state) noexcept : m_state(state) 147484543d1Sopenharmony_ci { 148484543d1Sopenharmony_ci } 149484543d1Sopenharmony_ci 150484543d1Sopenharmony_ci future() noexcept = default; 151484543d1Sopenharmony_ci 152484543d1Sopenharmony_ci future(future&& fut) noexcept 153484543d1Sopenharmony_ci { 154484543d1Sopenharmony_ci swap(fut); 155484543d1Sopenharmony_ci } 156484543d1Sopenharmony_ci future& operator=(future&& fut) noexcept 157484543d1Sopenharmony_ci { 158484543d1Sopenharmony_ci if (this != &fut) { 159484543d1Sopenharmony_ci future tmp(std::move(fut)); 160484543d1Sopenharmony_ci swap(tmp); 161484543d1Sopenharmony_ci } 162484543d1Sopenharmony_ci return *this; 163484543d1Sopenharmony_ci } 164484543d1Sopenharmony_ci 165484543d1Sopenharmony_ci bool valid() const noexcept 166484543d1Sopenharmony_ci { 167484543d1Sopenharmony_ci return m_state != nullptr; 168484543d1Sopenharmony_ci } 169484543d1Sopenharmony_ci 170484543d1Sopenharmony_ci R get() noexcept 171484543d1Sopenharmony_ci { 172484543d1Sopenharmony_ci auto tmp = std::move(m_state); 173484543d1Sopenharmony_ci if constexpr(!std::is_void_v<R>) { 174484543d1Sopenharmony_ci return std::move(tmp->get()); 175484543d1Sopenharmony_ci } else { 176484543d1Sopenharmony_ci return tmp->get(); 177484543d1Sopenharmony_ci } 178484543d1Sopenharmony_ci } 179484543d1Sopenharmony_ci 180484543d1Sopenharmony_ci template <typename Rep, typename Period> 181484543d1Sopenharmony_ci future_status wait_for(const std::chrono::duration<Rep, Period>& waitTime) const noexcept 182484543d1Sopenharmony_ci { 183484543d1Sopenharmony_ci return m_state->wait_for(waitTime); 184484543d1Sopenharmony_ci } 185484543d1Sopenharmony_ci 186484543d1Sopenharmony_ci template <typename Clock, typename Duration> 187484543d1Sopenharmony_ci future_status wait_until(const std::chrono::time_point<Clock, Duration>& tp) const noexcept 188484543d1Sopenharmony_ci { 189484543d1Sopenharmony_ci return m_state->wait_until(tp); 190484543d1Sopenharmony_ci } 191484543d1Sopenharmony_ci 192484543d1Sopenharmony_ci void wait() const noexcept 193484543d1Sopenharmony_ci { 194484543d1Sopenharmony_ci m_state->wait(); 195484543d1Sopenharmony_ci } 196484543d1Sopenharmony_ci 197484543d1Sopenharmony_ci void swap(future<R>& rhs) noexcept 198484543d1Sopenharmony_ci { 199484543d1Sopenharmony_ci std::swap(m_state, rhs.m_state); 200484543d1Sopenharmony_ci } 201484543d1Sopenharmony_ci 202484543d1Sopenharmony_ciprivate: 203484543d1Sopenharmony_ci std::shared_ptr<detail::shared_state<R>> m_state; 204484543d1Sopenharmony_ci}; 205484543d1Sopenharmony_ci 206484543d1Sopenharmony_citemplate <typename R> 207484543d1Sopenharmony_cistruct promise : private non_copyable { 208484543d1Sopenharmony_ci promise() noexcept : m_state {std::make_shared<detail::shared_state<R>>()} 209484543d1Sopenharmony_ci { 210484543d1Sopenharmony_ci } 211484543d1Sopenharmony_ci promise(promise&& p) noexcept 212484543d1Sopenharmony_ci { 213484543d1Sopenharmony_ci swap(p); 214484543d1Sopenharmony_ci } 215484543d1Sopenharmony_ci promise& operator=(promise&& p) noexcept 216484543d1Sopenharmony_ci { 217484543d1Sopenharmony_ci if (this != &p) { 218484543d1Sopenharmony_ci promise tmp(std::move(p)); 219484543d1Sopenharmony_ci swap(tmp); 220484543d1Sopenharmony_ci } 221484543d1Sopenharmony_ci return *this; 222484543d1Sopenharmony_ci } 223484543d1Sopenharmony_ci 224484543d1Sopenharmony_ci void set_value(const R& value) noexcept 225484543d1Sopenharmony_ci { 226484543d1Sopenharmony_ci m_state->set_value(value); 227484543d1Sopenharmony_ci } 228484543d1Sopenharmony_ci 229484543d1Sopenharmony_ci void set_value(R&& value) noexcept 230484543d1Sopenharmony_ci { 231484543d1Sopenharmony_ci m_state->set_value(std::move(value)); 232484543d1Sopenharmony_ci } 233484543d1Sopenharmony_ci 234484543d1Sopenharmony_ci future<R> get_future() noexcept 235484543d1Sopenharmony_ci { 236484543d1Sopenharmony_ci return future<R> {m_state}; 237484543d1Sopenharmony_ci } 238484543d1Sopenharmony_ci 239484543d1Sopenharmony_ci void swap(promise<R>& rhs) noexcept 240484543d1Sopenharmony_ci { 241484543d1Sopenharmony_ci std::swap(m_state, rhs.m_state); 242484543d1Sopenharmony_ci } 243484543d1Sopenharmony_ci 244484543d1Sopenharmony_ciprivate: 245484543d1Sopenharmony_ci std::shared_ptr<detail::shared_state<R>> m_state; 246484543d1Sopenharmony_ci}; 247484543d1Sopenharmony_ci 248484543d1Sopenharmony_citemplate <> 249484543d1Sopenharmony_cistruct promise<void> : private non_copyable { 250484543d1Sopenharmony_ci promise() noexcept : m_state {std::make_shared<detail::shared_state<void>>()} 251484543d1Sopenharmony_ci { 252484543d1Sopenharmony_ci } 253484543d1Sopenharmony_ci promise(promise&& p) noexcept 254484543d1Sopenharmony_ci { 255484543d1Sopenharmony_ci swap(p); 256484543d1Sopenharmony_ci } 257484543d1Sopenharmony_ci promise& operator=(promise&& p) noexcept 258484543d1Sopenharmony_ci { 259484543d1Sopenharmony_ci if (this != &p) { 260484543d1Sopenharmony_ci promise tmp(std::move(p)); 261484543d1Sopenharmony_ci swap(tmp); 262484543d1Sopenharmony_ci } 263484543d1Sopenharmony_ci return *this; 264484543d1Sopenharmony_ci } 265484543d1Sopenharmony_ci 266484543d1Sopenharmony_ci void set_value() noexcept 267484543d1Sopenharmony_ci { 268484543d1Sopenharmony_ci m_state->set_value(); 269484543d1Sopenharmony_ci } 270484543d1Sopenharmony_ci 271484543d1Sopenharmony_ci future<void> get_future() noexcept 272484543d1Sopenharmony_ci { 273484543d1Sopenharmony_ci return future<void> {m_state}; 274484543d1Sopenharmony_ci } 275484543d1Sopenharmony_ci 276484543d1Sopenharmony_ci void swap(promise<void>& rhs) noexcept 277484543d1Sopenharmony_ci { 278484543d1Sopenharmony_ci std::swap(m_state, rhs.m_state); 279484543d1Sopenharmony_ci } 280484543d1Sopenharmony_ci 281484543d1Sopenharmony_ciprivate: 282484543d1Sopenharmony_ci std::shared_ptr<detail::shared_state<void>> m_state; 283484543d1Sopenharmony_ci}; 284484543d1Sopenharmony_ci 285484543d1Sopenharmony_citemplate <typename F> 286484543d1Sopenharmony_cistruct packaged_task; 287484543d1Sopenharmony_ci 288484543d1Sopenharmony_citemplate <typename R, typename... Args> 289484543d1Sopenharmony_cistruct packaged_task<R(Args...)> { 290484543d1Sopenharmony_ci packaged_task() noexcept = default; 291484543d1Sopenharmony_ci 292484543d1Sopenharmony_ci packaged_task(const packaged_task& pt) noexcept 293484543d1Sopenharmony_ci { 294484543d1Sopenharmony_ci m_fn = pt.m_fn; 295484543d1Sopenharmony_ci m_state = pt.m_state; 296484543d1Sopenharmony_ci } 297484543d1Sopenharmony_ci 298484543d1Sopenharmony_ci packaged_task(packaged_task&& pt) noexcept 299484543d1Sopenharmony_ci { 300484543d1Sopenharmony_ci swap(pt); 301484543d1Sopenharmony_ci } 302484543d1Sopenharmony_ci 303484543d1Sopenharmony_ci packaged_task& operator=(packaged_task&& pt) noexcept 304484543d1Sopenharmony_ci { 305484543d1Sopenharmony_ci if (this != &pt) { 306484543d1Sopenharmony_ci packaged_task tmp(std::move(pt)); 307484543d1Sopenharmony_ci swap(tmp); 308484543d1Sopenharmony_ci } 309484543d1Sopenharmony_ci return *this; 310484543d1Sopenharmony_ci } 311484543d1Sopenharmony_ci 312484543d1Sopenharmony_ci template <typename F> 313484543d1Sopenharmony_ci explicit packaged_task(F&& f) noexcept 314484543d1Sopenharmony_ci : m_fn {std::forward<F>(f)}, m_state {std::make_shared<detail::shared_state<R>>()} 315484543d1Sopenharmony_ci { 316484543d1Sopenharmony_ci } 317484543d1Sopenharmony_ci 318484543d1Sopenharmony_ci bool valid() const noexcept 319484543d1Sopenharmony_ci { 320484543d1Sopenharmony_ci return bool(m_fn) && m_state != nullptr; 321484543d1Sopenharmony_ci } 322484543d1Sopenharmony_ci 323484543d1Sopenharmony_ci future<R> get_future() noexcept 324484543d1Sopenharmony_ci { 325484543d1Sopenharmony_ci return future<R> {m_state}; 326484543d1Sopenharmony_ci } 327484543d1Sopenharmony_ci 328484543d1Sopenharmony_ci void operator()(Args... args) 329484543d1Sopenharmony_ci { 330484543d1Sopenharmony_ci if constexpr(!std::is_void_v<R>) { 331484543d1Sopenharmony_ci m_state->set_value(m_fn(std::forward<Args>(args)...)); 332484543d1Sopenharmony_ci } else { 333484543d1Sopenharmony_ci m_fn(std::forward<Args>(args)...); 334484543d1Sopenharmony_ci m_state->set_value(); 335484543d1Sopenharmony_ci } 336484543d1Sopenharmony_ci } 337484543d1Sopenharmony_ci 338484543d1Sopenharmony_ci void swap(packaged_task& pt) noexcept 339484543d1Sopenharmony_ci { 340484543d1Sopenharmony_ci std::swap(m_fn, pt.m_fn); 341484543d1Sopenharmony_ci std::swap(m_state, pt.m_state); 342484543d1Sopenharmony_ci } 343484543d1Sopenharmony_ci 344484543d1Sopenharmony_ciprivate: 345484543d1Sopenharmony_ci std::function<R(Args...)> m_fn; 346484543d1Sopenharmony_ci std::shared_ptr<detail::shared_state<R>> m_state; 347484543d1Sopenharmony_ci}; 348484543d1Sopenharmony_ci 349484543d1Sopenharmony_citemplate <typename F, typename... Args> 350484543d1Sopenharmony_cifuture<std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>> async(F&& f, Args&& ... args) 351484543d1Sopenharmony_ci{ 352484543d1Sopenharmony_ci using R = std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>; 353484543d1Sopenharmony_ci packaged_task<R(std::decay_t<Args>...)> pt {std::forward<F>(f)}; 354484543d1Sopenharmony_ci auto fut {pt.get_future()}; 355484543d1Sopenharmony_ci auto th = ffrt::thread(std::move(pt), std::forward<Args>(args)...); 356484543d1Sopenharmony_ci th.detach(); 357484543d1Sopenharmony_ci return fut; 358484543d1Sopenharmony_ci} 359484543d1Sopenharmony_ci} // namespace ffrt 360484543d1Sopenharmony_ci#endif 361