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 //! Asynchronous tasks that wraps the future and get scheduled by the runtime.
15 
16 pub mod builder;
17 pub mod join_handle;
18 mod join_set;
19 mod raw;
20 pub(crate) mod state;
21 mod task_handle;
22 mod waker;
23 pub(crate) mod yield_now;
24 use std::future::Future;
25 use std::ptr::NonNull;
26 use std::sync::Weak;
27 
28 pub use builder::TaskBuilder;
29 pub use join_handle::JoinHandle;
30 pub use join_set::JoinSet;
31 pub use yield_now::yield_now;
32 
33 use crate::executor::Schedule;
34 pub(crate) use crate::task::raw::{Header, RawTask, TaskMngInfo};
35 
36 pub(crate) enum VirtualTableType {
37     #[cfg(not(feature = "ffrt"))]
38     Ylong,
39     #[cfg(feature = "ffrt")]
40     Ffrt,
41 }
42 
43 #[cfg(not(feature = "ffrt"))]
44 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
45 /// Qos levels.
46 pub enum Qos {
47     /// Inherits parent's qos level
48     Inherent = -1,
49     /// Lowest qos
50     Background,
51     /// Utility qos
52     Utility,
53     /// Default qos
54     Default,
55     /// User initialiated qos
56     UserInitiated,
57     /// Deadline qos
58     DeadlineRequest,
59     /// Highest qos
60     UserInteractive,
61 }
62 
63 #[cfg(feature = "ffrt")]
64 pub use ylong_ffrt::Qos;
65 
66 #[repr(transparent)]
67 #[derive(Clone)]
68 pub(crate) struct Task(pub(crate) RawTask);
69 
70 unsafe impl Send for Task {}
71 unsafe impl Sync for Task {}
72 
73 #[cfg(not(feature = "ffrt"))]
74 impl Task {
75     #[inline]
run(self)76     pub(crate) fn run(self) {
77         self.0.run();
78     }
79 
80     #[inline]
shutdown(self)81     pub(crate) fn shutdown(self) {
82         self.0.shutdown();
83     }
84 
85     #[inline]
into_header(self) -> NonNull<Header>86     pub(crate) fn into_header(self) -> NonNull<Header> {
87         self.0.ptr
88     }
89 
90     #[inline]
from_raw(ptr: NonNull<Header>) -> Task91     pub(crate) unsafe fn from_raw(ptr: NonNull<Header>) -> Task {
92         Task(RawTask::form_raw(ptr))
93     }
94 }
95 
96 impl Task {
create_task<T, S>( builder: &TaskBuilder, scheduler: Weak<S>, task: T, virtual_table_type: VirtualTableType, ) -> (Task, JoinHandle<T::Output>) where T: Future + Send + 'static, T::Output: Send + 'static, S: Schedule,97     pub(crate) fn create_task<T, S>(
98         builder: &TaskBuilder,
99         scheduler: Weak<S>,
100         task: T,
101         virtual_table_type: VirtualTableType,
102     ) -> (Task, JoinHandle<T::Output>)
103     where
104         T: Future + Send + 'static,
105         T::Output: Send + 'static,
106         S: Schedule,
107     {
108         let raw = Task::create_raw_task::<T, S>(builder, scheduler, task, virtual_table_type);
109 
110         let join = JoinHandle::new(raw);
111         (Task(raw), join)
112     }
113 
create_raw_task<T, S>( builder: &TaskBuilder, scheduler: Weak<S>, task: T, virtual_table_type: VirtualTableType, ) -> RawTask where T: Future, S: Schedule,114     pub(crate) fn create_raw_task<T, S>(
115         builder: &TaskBuilder,
116         scheduler: Weak<S>,
117         task: T,
118         virtual_table_type: VirtualTableType,
119     ) -> RawTask
120     where
121         T: Future,
122         S: Schedule,
123     {
124         let ptr = Box::into_raw(TaskMngInfo::<T, S>::new(
125             builder,
126             scheduler,
127             task,
128             virtual_table_type,
129         ));
130         let non_ptr = NonNull::new(ptr.cast::<Header>());
131         let ptr = if let Some(ptr) = non_ptr {
132             ptr
133         } else {
134             panic!("task mem is null because not enough memory is available");
135         };
136         RawTask { ptr }
137     }
138 }
139 
140 /// Using the default task setting, spawns a task onto the global runtime.
spawn<T, R>(task: T) -> JoinHandle<R> where T: Future<Output = R>, T: Send + 'static, R: Send + 'static,141 pub fn spawn<T, R>(task: T) -> JoinHandle<R>
142 where
143     T: Future<Output = R>,
144     T: Send + 'static,
145     R: Send + 'static,
146 {
147     TaskBuilder::new().spawn(task)
148 }
149 
150 /// Using the default task setting, spawns a blocking task.
spawn_blocking<T, R>(task: T) -> JoinHandle<R> where T: FnOnce() -> R, T: Send + 'static, R: Send + 'static,151 pub fn spawn_blocking<T, R>(task: T) -> JoinHandle<R>
152 where
153     T: FnOnce() -> R,
154     T: Send + 'static,
155     R: Send + 'static,
156 {
157     TaskBuilder::new().spawn_blocking(task)
158 }
159 
160 /// Blocks the current thread until the `Future` passed in is completed.
block_on<T>(task: T) -> T::Output where T: Future,161 pub fn block_on<T>(task: T) -> T::Output
162 where
163     T: Future,
164 {
165     let rt = crate::executor::global_default_async();
166     rt.block_on(task)
167 }
168