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::convert::TryInto;
15 use std::future::Future;
16 use std::pin::Pin;
17 use std::task::{Context, Poll};
18 use std::time::{Duration, Instant};
19
20 const TEN_YEARS: Duration = Duration::from_secs(86400 * 365 * 10);
21
22 /// Waits until 'instant' has reached.
23 ///
24 /// # Panic
25 /// Calling this method outside of a Ylong Runtime could cause panic, for
26 /// example, outside of an async closure that is passed to ylong_runtime::spawn
27 /// or ylong_runtime::block_on. The async wrapping is necessary since it makes
28 /// the function become lazy in order to get successfully executed on the
29 /// runtime.
sleep_until(instant: Instant) -> Sleep30 pub fn sleep_until(instant: Instant) -> Sleep {
31 Sleep::new_timeout(instant)
32 }
33
34 /// Waits until 'duration' has elapsed.
35 ///
36 /// # Panic
37 /// Calling this method outside of a Ylong Runtime could cause panic, for
38 /// example, outside of an async closure that is passed to ylong_runtime::spawn
39 /// or ylong_runtime::block_on. The async wrapping is necessary since it makes
40 /// the function become lazy in order to get successfully executed on the
41 /// runtime.
sleep(duration: Duration) -> Sleep42 pub fn sleep(duration: Duration) -> Sleep {
43 // If the time reaches the maximum value,
44 // then set the default timing time to 10 years.
45 match Instant::now().checked_add(duration) {
46 Some(deadline) => Sleep::new_timeout(deadline),
47 None => Sleep::new_timeout(Instant::now() + TEN_YEARS),
48 }
49 }
50
51 /// A structure that implements Future. returned by func [`sleep`].
52 ///
53 /// [`sleep`]: sleep
54 /// # Examples
55 ///
56 /// ```
57 /// use std::time::Duration;
58 ///
59 /// use ylong_runtime::time::sleep;
60 ///
61 /// async fn sleep_test() {
62 /// let sleep = sleep(Duration::from_secs(2)).await;
63 /// println!("2 secs have elapsed");
64 /// }
65 /// ```
66 pub struct Sleep {
67 // During the polling of this structure, no repeated insertion.
68 need_insert: bool,
69
70 // The time at which the structure should end.
71 deadline: Instant,
72
73 inner: SleepInner,
74 }
75
76 cfg_ffrt!(
77 use crate::ffrt::ffrt_timer::FfrtTimerEntry;
78 use std::task::Waker;
79
80 struct SleepInner {
81 // ffrt timer handle
82 timer: Option<FfrtTimerEntry>,
83 // the waker to wakeup the timer task
84 waker: Option<*mut Waker>,
85 }
86
87 // FFRT needs this unsafe impl since `Sleep` has a mut pointer in it.
88 // In non-ffrt environment, `Sleep` auto-derives Sync & Send.
89 unsafe impl Send for Sleep {}
90 unsafe impl Sync for Sleep {}
91
92 impl Sleep {
93 // Creates a Sleep structure based on the given deadline.
94 fn new_timeout(deadline: Instant) -> Self {
95 Self {
96 need_insert: true,
97 deadline,
98 inner: SleepInner {
99 timer: None,
100 waker: None,
101 }
102 }
103 }
104
105 // Resets the deadline of the Sleep
106 pub(crate) fn reset(&mut self, new_deadline: Instant) {
107 self.need_insert = true;
108 self.deadline = new_deadline;
109
110 if let Some(waker) = self.inner.waker.take() {
111 unsafe {
112 drop(Box::from_raw(waker as *mut Waker));
113 }
114 }
115 }
116
117 // Cancels the Sleep
118 fn cancel(&mut self) {
119 if let Some(timer) = self.inner.timer.take() {
120 timer.timer_deregister();
121 }
122 if let Some(waker) = self.inner.waker.take() {
123 unsafe {
124 drop(Box::from_raw(waker as *mut Waker));
125 }
126 }
127 }
128 }
129
130 impl Future for Sleep {
131 type Output = ();
132
133 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
134 let this = self.get_mut();
135
136 if this.need_insert {
137 if let Some(duration) = this.deadline.checked_duration_since(Instant::now()) {
138 let ms = duration.as_millis()
139 .try_into()
140 .unwrap_or(u64::MAX);
141
142 let waker = Box::new(cx.waker().clone());
143 let waker_ptr = Box::into_raw(waker);
144
145 if let Some(waker) = this.inner.waker.take() {
146 unsafe { drop(Box::from_raw(waker as *mut Waker)); }
147 }
148
149 this.inner.waker = Some(waker_ptr);
150 this.inner.timer = Some(FfrtTimerEntry::timer_register(waker_ptr, ms));
151 this.need_insert = false;
152 } else {
153 return Poll::Ready(());
154 }
155 }
156
157 // this unwrap is safe since we have already insert the timer into the entry
158 let timer = this.inner.timer.as_ref().unwrap();
159 if timer.result() {
160 Poll::Ready(())
161 } else {
162 Poll::Pending
163 }
164 }
165 }
166 );
167
168 impl Sleep {
169 // Returns the deadline of the Sleep
deadline(&self) -> Instant170 pub(crate) fn deadline(&self) -> Instant {
171 self.deadline
172 }
173 }
174
175 cfg_not_ffrt!(
176 use crate::executor::driver::Handle;
177 use crate::time::Clock;
178 use std::sync::Arc;
179 use std::cmp;
180 use std::ptr::NonNull;
181
182 struct SleepInner {
183 // Corresponding Timer structure.
184 timer: Clock,
185 // Timer driver handle
186 handle: Arc<Handle>,
187 }
188
189 impl Sleep {
190 // Creates a Sleep structure based on the given deadline.
191 fn new_timeout(deadline: Instant) -> Self {
192 let handle = Handle::get_handle().expect("sleep new out of worker ctx");
193
194 let start_time = handle.start_time();
195 let deadline = cmp::max(deadline, start_time);
196
197 let timer = Clock::new();
198 Self {
199 need_insert: true,
200 deadline,
201 inner: SleepInner {
202 timer,
203 handle,
204 }
205 }
206 }
207
208 // Resets the deadline of the Sleep
209 pub(crate) fn reset(&mut self, new_deadline: Instant) {
210 self.need_insert = true;
211 self.deadline = new_deadline;
212 self.inner.timer.set_result(false);
213 }
214
215 // Cancels the Sleep
216 fn cancel(&mut self) {
217 let driver = &self.inner.handle;
218 driver.timer_cancel(NonNull::from(&self.inner.timer));
219 }
220 }
221
222 impl Future for Sleep {
223 type Output = ();
224
225 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
226 let this = self.get_mut();
227 let driver = &this.inner.handle;
228
229 if this.need_insert {
230 let ms = this
231 .deadline
232 .checked_duration_since(driver.start_time())
233 .unwrap()
234 .as_millis()
235 .try_into()
236 .unwrap_or(u64::MAX);
237 this.inner.timer.set_expiration(ms);
238 this.inner.timer.set_waker(cx.waker().clone());
239
240 match driver.timer_register(NonNull::from(&this.inner.timer)) {
241 Ok(_) => this.need_insert = false,
242 Err(_) => {
243 // Even if the insertion fails, there is no need to insert again here,
244 // it is a timeout clock and needs to be triggered immediately at the next poll.
245 this.need_insert = false;
246 this.inner.timer.set_result(true);
247 }
248 }
249 }
250
251 if this.inner.timer.result() {
252 Poll::Ready(())
253 } else {
254 Poll::Pending
255 }
256 }
257 }
258 );
259
260 impl Drop for Sleep {
drop(&mut self)261 fn drop(&mut self) {
262 // For some uses, for example, Timeout,
263 // `Sleep` enters the `Pending` state first and inserts the `TimerHandle` into
264 // the `DRIVER`, the future of timeout returns `Ready` in advance of the
265 // next polling, as a result, the `TimerHandle` pointer in the `DRIVER`
266 // is invalid. need to cancel the `TimerHandle` operation during `Sleep`
267 // drop.
268 self.cancel()
269 }
270 }
271
272 #[cfg(test)]
273 mod test {
274 use std::time::Duration;
275
276 use crate::time::sleep;
277 use crate::{block_on, spawn};
278
279 /// UT test cases for new_sleep
280 ///
281 /// # Brief
282 /// 1. Uses sleep to create a Sleep Struct.
283 /// 2. Uses block_on to test different sleep duration.
284 #[test]
new_timer_sleep()285 fn new_timer_sleep() {
286 block_on(async move {
287 sleep(Duration::new(0, 20_000_000)).await;
288 sleep(Duration::new(0, 20_000_000)).await;
289 sleep(Duration::new(0, 20_000_000)).await;
290 });
291
292 let handle_one = spawn(async {
293 sleep(Duration::new(0, 20_000_000)).await;
294 });
295 let handle_two = spawn(async {
296 sleep(Duration::new(0, 20_000_000)).await;
297 });
298 let handle_three = spawn(async {
299 sleep(Duration::new(0, 20_000_000)).await;
300 });
301 block_on(handle_one).unwrap();
302 block_on(handle_two).unwrap();
303 block_on(handle_three).unwrap();
304 }
305 }
306