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