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