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::mem;
26 use std::ptr::NonNull;
27 use std::sync::Weak;
28
29 pub use builder::TaskBuilder;
30 pub use join_handle::JoinHandle;
31 pub use join_set::JoinSet;
32 pub use yield_now::yield_now;
33
34 use crate::executor::Schedule;
35 use crate::task::raw::{Header, RawTask, TaskMngInfo};
36
37 pub(crate) enum VirtualTableType {
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 impl Task {
run(self)74 pub(crate) fn run(self) {
75 self.0.run();
76 mem::forget(self);
77 }
78 #[cfg(not(feature = "ffrt"))]
shutdown(self)79 pub(crate) fn shutdown(self) {
80 self.0.shutdown();
81 }
82 }
83
84 impl Task {
from_raw(ptr: NonNull<Header>) -> Task85 pub(crate) unsafe fn from_raw(ptr: NonNull<Header>) -> Task {
86 Task(RawTask::form_raw(ptr))
87 }
88
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,89 pub(crate) fn create_task<T, S>(
90 builder: &TaskBuilder,
91 scheduler: Weak<S>,
92 task: T,
93 virtual_table_type: VirtualTableType,
94 ) -> (Task, JoinHandle<T::Output>)
95 where
96 T: Future + Send + 'static,
97 T::Output: Send + 'static,
98 S: Schedule,
99 {
100 let raw = Task::create_raw_task::<T, S>(builder, scheduler, task, virtual_table_type);
101
102 let join = JoinHandle::new(raw);
103 (Task(raw), join)
104 }
105
create_raw_task<T, S>( builder: &TaskBuilder, scheduler: Weak<S>, task: T, virtual_table_type: VirtualTableType, ) -> RawTask where T: Future, S: Schedule,106 pub(crate) fn create_raw_task<T, S>(
107 builder: &TaskBuilder,
108 scheduler: Weak<S>,
109 task: T,
110 virtual_table_type: VirtualTableType,
111 ) -> RawTask
112 where
113 T: Future,
114 S: Schedule,
115 {
116 let ptr = Box::into_raw(TaskMngInfo::<T, S>::new(
117 builder,
118 scheduler,
119 task,
120 virtual_table_type,
121 ));
122 let non_ptr = NonNull::new(ptr as *mut Header);
123 let ptr = if let Some(ptr) = non_ptr {
124 ptr
125 } else {
126 panic!("task mem is null because not enough memory is available");
127 };
128 RawTask { ptr }
129 }
130 }
131
132 impl Drop for Task {
drop(&mut self)133 fn drop(&mut self) {
134 self.0.drop_ref()
135 }
136 }
137
138 /// 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,139 pub fn spawn<T, R>(task: T) -> JoinHandle<R>
140 where
141 T: Future<Output = R>,
142 T: Send + 'static,
143 R: Send + 'static,
144 {
145 TaskBuilder::new().spawn(task)
146 }
147
148 /// 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,149 pub fn spawn_blocking<T, R>(task: T) -> JoinHandle<R>
150 where
151 T: FnOnce() -> R,
152 T: Send + 'static,
153 R: Send + 'static,
154 {
155 TaskBuilder::new().spawn_blocking(task)
156 }
157
158 /// Blocks the current thread until the `Future` passed in is completed.
block_on<T>(task: T) -> T::Output where T: Future,159 pub fn block_on<T>(task: T) -> T::Output
160 where
161 T: Future,
162 {
163 let rt = crate::executor::global_default_async();
164 rt.block_on(task)
165 }
166