1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::future::Future;
15 
16 use crate::executor::global_default_async;
17 use crate::task::join_handle::JoinHandle;
18 use crate::task::TaskBuilder;
19 
20 cfg_not_ffrt! {
21     use crate::executor::global_default_blocking;
22 }
23 
24 cfg_ffrt! {
25     use std::pin::Pin;
26     use std::task::{Context, Poll};
27     use crate::ffrt::spawner::spawn;
28 
29     struct BlockingTask<T>(Option<T>);
30 
31     impl<T> Unpin for BlockingTask<T> {}
32 
33     impl<T, R> Future for BlockingTask<T>
34         where
35             T: FnOnce() -> R,
36     {
37         type Output = R;
38 
39         fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
40             // Task won't be polled again after finished
41             let func = self.0.take().expect("blocking tasks cannot be polled after finished");
42             Poll::Ready(func())
43         }
44     }
45 
46     /// Spawns a task on the blocking pool.
47     pub(crate) fn spawn_blocking<T, R>(builder: &TaskBuilder, task: T) -> JoinHandle<R>
48         where
49             T: FnOnce() -> R,
50             T: Send + 'static,
51             R: Send + 'static,
52     {
53         let task = BlockingTask(Some(task));
54         spawn(task, builder)
55     }
56 }
57 
58 #[cfg(not(feature = "ffrt"))]
59 /// Spawns a task on the blocking pool.
spawn_blocking<T, R>(builder: &TaskBuilder, task: T) -> JoinHandle<R> where T: FnOnce() -> R, T: Send + 'static, R: Send + 'static,60 pub(crate) fn spawn_blocking<T, R>(builder: &TaskBuilder, task: T) -> JoinHandle<R>
61 where
62     T: FnOnce() -> R,
63     T: Send + 'static,
64     R: Send + 'static,
65 {
66     let rt = global_default_blocking();
67     rt.spawn_blocking(builder, task)
68 }
69 
70 /// Gets global default executor, spawns async tasks by the task builder, and
71 /// returns.
72 #[inline]
spawn_async<T, R>(builder: &TaskBuilder, task: T) -> JoinHandle<R> where T: Future<Output = R>, T: Send + 'static, R: Send + 'static,73 pub(crate) fn spawn_async<T, R>(builder: &TaskBuilder, task: T) -> JoinHandle<R>
74 where
75     T: Future<Output = R>,
76     T: Send + 'static,
77     R: Send + 'static,
78 {
79     let rt = global_default_async();
80     rt.spawn_with_attr(task, builder)
81 }
82