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