async_deferred/lib.rs
1use std::sync::Arc;
2
3use tokio::sync::OnceCell;
4use tokio::task::JoinHandle;
5use std::future::Future;
6
7/// Represents the current state of an asynchronous task.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum State {
10 /// The task hasn't been started yet.
11 NotInitialized,
12 /// The task is currently running.
13 Pending,
14 /// The task has completed successfully and returned a value.
15 Completed,
16 /// The task panicked during execution.
17 TaskPanicked(String),
18 /// The callback panicked during execution.
19 CallbackPanicked(String),
20
21}
22
23/// A handle to an asynchronous computation that allows for deferred result retrieval.
24///
25/// This struct supports the "fire-and-forget" pattern with the ability to later query the result
26/// or detect if the task panicked. It's useful when you want to start a computation but don't
27/// need the result immediately.
28///
29/// # Examples
30///
31/// ```rust
32/// use async_deferred::Deferred;
33///
34/// # tokio_test::block_on(async {
35/// // Start a computation immediately
36/// let mut deferred = Deferred::start(|| async {
37/// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
38/// 42
39/// });
40///
41/// // Later, get the result
42/// let result = deferred.join().await.try_get();
43/// assert_eq!(result, Some(&42));
44/// # })
45/// ```
46///
47/// ```
48/// // Create and start manually
49/// use async_deferred::Deferred;
50///
51/// # tokio_test::block_on(async {
52/// let mut deferred = Deferred::new();
53/// deferred.begin(|| async { "Hello, World!" });
54///
55/// // Check if ready without blocking (might not be ready yet)
56/// match deferred.try_get() {
57/// Some(result) => println!("Result: {}", result),
58/// None => println!("Not ready yet"),
59/// }
60/// # })
61/// ```
62///
63/// # Thread Safety
64///
65/// `Deferred<T>` is `Send` and `Sync` when `T` is `Send` and `Sync`, making it safe to
66/// share across threads and async tasks.
67///
68/// # Memory Management
69///
70/// Internally, the task runs on Tokio's async runtime, and the result is stored in a `OnceCell`.
71/// The computation runs independently and the result is cached until retrieved via `take()` or
72/// the `Deferred` is dropped.
73#[derive(Debug)]
74pub struct Deferred<T> {
75 value: Arc<OnceCell<T>>,
76 task_handle: Option<JoinHandle<()>>,
77 panic_message: Option<String>,
78 is_callback_panic: bool,
79}
80
81impl<T> Deferred<T>
82where
83 T: Send + Sync + 'static,
84{
85 /// Creates a new empty `Deferred` instance.
86 ///
87 /// The task must be started manually using [`begin`](Self::begin) or [`begin_with_callback`](Self::begin_with_callback).
88 ///
89 /// # Examples
90 ///
91 /// ```rust
92 /// use async_deferred::Deferred;
93 ///
94 /// # tokio_test::block_on(async {
95 /// let mut deferred = Deferred::new();
96 /// assert!(deferred.is_not_initialized());
97 ///
98 /// deferred.begin(|| async { 42 });
99 /// assert!(!deferred.is_not_initialized());
100 /// # })
101 /// ```
102 pub fn new() -> Self {
103 Self {
104 value: Arc::new(OnceCell::new()),
105 task_handle: None,
106 panic_message: None,
107 is_callback_panic: false
108 }
109 }
110
111 /// Starts a new asynchronous task and returns a `Deferred` handle.
112 ///
113 /// This is a convenient way to construct and start the deferred task in one step.
114 ///
115 /// # Arguments
116 /// * `computation` - An async function or closure that returns the result of the task.
117 ///
118 /// # Examples
119 ///
120 /// ```
121 /// use async_deferred::Deferred;
122 ///
123 /// # tokio_test::block_on(async {
124 /// let deferred = Deferred::start(|| async {
125 /// // Some computation
126 /// 42
127 /// });
128 ///
129 /// // Task is already running
130 /// assert!(deferred.is_pending() || deferred.is_ready());
131 /// # })
132 /// ```
133 pub fn start<F, Fut>(computation: F) -> Self
134 where
135 F: FnOnce() -> Fut + Send + 'static,
136 Fut: Future<Output = T> + Send + 'static,
137 {
138 let mut deferred = Self::new();
139 deferred.begin(computation);
140 deferred
141 }
142
143 /// Starts a new asynchronous task with a callback that is called once the task completes.
144 ///
145 /// The callback is executed after the computation finishes, regardless of whether it
146 /// succeeded or panicked. This is useful for logging, cleanup, or notifications.
147 ///
148 /// # Arguments
149 /// * `computation` - An async function or closure that returns the result of the task.
150 /// * `callback` - A closure that will be run after the task completes.
151 ///
152 /// # Examples
153 ///
154 /// ```rust
155 /// use async_deferred::Deferred;
156 /// # tokio_test::block_on(async {
157 /// let deferred = Deferred::start_with_callback(
158 /// || async { 42 },
159 /// || println!("Computation finished!")
160 /// );
161 /// # })
162 /// ```
163 pub fn start_with_callback<F, C, Fut>(computation: F, callback: C) -> Self
164 where
165 F: FnOnce() -> Fut + Send + 'static,
166 C: FnOnce() + Send + 'static,
167 Fut: Future<Output = T> + Send + 'static,
168 {
169 let mut deferred = Self::new();
170 deferred.begin_with_callback(computation, callback);
171 deferred
172 }
173
174 /// Begins execution of the deferred task.
175 ///
176 /// Returns `true` if the task was successfully started, or `false` if it has already
177 /// been started or completed.
178 ///
179 /// # Arguments
180 /// * `computation` - An async function or closure that returns the result of the task.
181 ///
182 /// # Examples
183 ///
184 /// ```rust
185 /// use async_deferred::Deferred;
186 /// # tokio_test::block_on(async {
187 /// let mut deferred = Deferred::new();
188 ///
189 /// assert!(deferred.begin(|| async { 42 })); // Started successfully
190 /// assert!(!deferred.begin(|| async { 24 })); // Already started, returns false
191 ///
192 /// # })
193 /// ```
194 pub fn begin<F, Fut>(&mut self, computation: F) -> bool
195 where
196 F: FnOnce() -> Fut + Send + 'static,
197 Fut: Future<Output = T> + Send + 'static,
198 {
199 self._begin(computation, None::<fn()>)
200 }
201
202 /// Begins execution of the deferred task and executes a callback after completion.
203 ///
204 /// Returns `true` if the task was successfully started, or `false` if it has already
205 /// been started or completed.
206 ///
207 /// # Arguments
208 /// * `computation` - An async function or closure that returns the result of the task.
209 /// * `callback` - A closure that will be run after the task completes.
210 ///
211 /// # Examples
212 ///
213 /// ```rust
214 /// use async_deferred::Deferred;
215 ///
216 /// # tokio_test::block_on(async {
217 /// let mut deferred = Deferred::new();
218 ///
219 /// let started = deferred.begin_with_callback(
220 /// || async { 42 },
221 /// || println!("Task completed!")
222 /// );
223 /// assert!(started);
224 /// # })
225 /// ```
226 pub fn begin_with_callback<F, C, Fut>(&mut self, computation: F, callback: C) -> bool
227 where
228 F: FnOnce() -> Fut + Send + 'static,
229 C: FnOnce() + Send + 'static,
230 Fut: Future<Output = T> + Send + 'static,
231 {
232 self._begin(computation, Some(callback))
233 }
234
235 /// Internal implementation for starting tasks with optional callbacks.
236 fn _begin<F, C, Fut>(&mut self, computation: F, callback: Option<C>) -> bool
237 where
238 F: FnOnce() -> Fut + Send + 'static,
239 C: FnOnce() + Send + 'static,
240 Fut: Future<Output = T> + Send + 'static,
241 {
242 if !self.is_not_initialized() {
243 return false;
244 }
245
246 let cell = self.value.clone();
247
248 let handle = tokio::spawn(async move {
249 let result = computation().await;
250 let _ = cell.set(result);
251 if let Some(callback) = callback {
252 callback();
253 }
254 });
255
256 self.task_handle = Some(handle);
257 true
258 }
259
260 /// Returns the current state of the task.
261 ///
262 /// # Returns
263 /// - `State::NotInitialized` - The task hasn't been started yet
264 /// - `State::Pending` - The task is currently running
265 /// - `State::Completed` - The task completed successfully or the callback panicked
266 /// - `State::TaskPanicked` - The task panicked during execution
267 ///
268 /// [`state`](Self::state) only detects if the task has panicked and not the callback.
269 /// If you need this information, use [`join`](Self::join) or [`state_async`](Self::state_async).
270 ///
271 /// # Examples
272 ///
273 /// ```rust
274 /// use async_deferred::{Deferred, State};
275 ///
276 /// # tokio_test::block_on(async {
277 /// let mut deferred: Deferred<u32> = Deferred::new();
278 /// assert!(matches!(deferred.state(), State::NotInitialized));
279 /// deferred.begin(|| async {
280 /// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
281 /// 42
282 /// });
283 /// assert!(matches!(deferred.state(), State::Pending));
284 /// tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
285 /// assert!(matches!(deferred.state(), State::Completed));
286 /// # })
287 /// ```
288 /// If panicked due to the callback, [`state`](Self::state) will return State::Completed.
289 /// ```rust
290 /// use async_deferred::{Deferred, State};
291 ///
292 /// # tokio_test::block_on(async {
293 /// let mut deferred: Deferred<u32> = Deferred::start_with_callback(
294 /// || async {42},
295 /// || {panic!("the callback panicked");},
296 /// );
297 /// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
298 ///
299 /// // state only detects if the task has panicked and not the callback
300 /// assert!(matches!(deferred.state(), State::Completed));
301 /// # })
302 /// ```
303 pub fn state(&self) -> State {
304 // If we already detected a panic, return the appropriate state
305 if let Some(panic_msg) = &self.panic_message {
306 return if self.is_callback_panic {
307 State::CallbackPanicked(panic_msg.clone())
308 } else {
309 State::TaskPanicked(panic_msg.clone())
310 };
311 }
312
313 // Check if we have a task handle
314 if let Some(handle) = &self.task_handle {
315 if handle.is_finished() {
316 // Task is finished, but we can't check for panic synchronously
317 // We'll need to await the result in an async context
318 // For now, if the task is finished but we don't have a result, assume it panicked
319 if self.is_ready() {
320 State::Completed
321 } else {
322 // Task finished but no result - likely panicked
323 // We'll set a default message until we can properly check
324 State::TaskPanicked("Task may have panicked (use join() to get details)".to_string())
325 }
326 } else if self.is_ready() {
327 // Task is still running but result is available (shouldn't happen)
328 State::Completed
329 } else {
330 // Task is still running
331 State::Pending
332 }
333 } else if self.is_ready() {
334 // handle may be none if the handle has been consumed by the join
335 State::Completed
336 } else {
337 State::NotInitialized
338 }
339 }
340
341
342 /// Returns the current state of the task. This method is able to correctly
343 /// diagnose when a given callback panics, as opposed to [`state`](Self::state).
344 /// Though asynchronous, it will not block until the task completes.
345 ///
346 /// # Returns
347 /// - `State::NotInitialized` - The task hasn't been started yet
348 /// - `State::Pending` - The task is currently running
349 /// - `State::Completed` - The task completed successfully
350 /// - `State::TaskPanicked` - The task panicked during execution
351 /// - `State::CallbackPanicked` - The callback panicked during execution
352 ///
353 /// # Examples
354 /// ```rust
355 /// use async_deferred::{Deferred, State};
356 ///
357 /// # tokio_test::block_on(async {
358 /// let mut deferred: Deferred<u32> = Deferred::new();
359 /// assert!(matches!(deferred.state_async().await, State::NotInitialized));
360 /// deferred.begin(|| async {
361 /// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
362 /// 42
363 /// });
364 ///
365 /// // The task is not done yet
366 /// assert!(matches!(deferred.state_async().await, State::Pending));
367 ///
368 /// tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
369 ///
370 /// // The task is completed
371 /// assert!(matches!(deferred.state_async().await, State::Completed));
372 /// # })
373 /// ```
374 ///
375 /// ```rust
376 /// use async_deferred::{Deferred, State};
377 ///
378 /// # tokio_test::block_on(async {
379 /// let mut deferred: Deferred<u32> = Deferred::start_with_callback(
380 /// || async { panic!("the task panicked"); 42 },
381 /// || { panic!("callback will not be called since the task panicked"); },
382 /// );
383 /// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
384 ///
385 /// assert!(matches!(deferred.state_async().await, State::TaskPanicked(_)));
386 /// # })
387 /// ```
388 ///
389 /// ```rust
390 /// use async_deferred::{Deferred, State};
391 ///
392 /// # tokio_test::block_on(async {
393 /// let mut deferred: Deferred<u32> = Deferred::start_with_callback(
394 /// || async { 42 },
395 /// || { panic!("the callback panicked"); },
396 /// );
397 /// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
398 ///
399 /// assert!(matches!(deferred.state_async().await, State::CallbackPanicked(_)));
400 /// # })
401 pub async fn state_async(&mut self) -> State {
402 // If we already detected a panic, return the appropriate state
403 if let Some(panic_msg) = &self.panic_message {
404 return if self.is_callback_panic {
405 State::CallbackPanicked(panic_msg.clone())
406 } else {
407 State::TaskPanicked(panic_msg.clone())
408 };
409 }
410
411 // Check if we have a task handle
412 if let Some(handle) = &self.task_handle {
413 if handle.is_finished() {
414 // We can safely await the finished task
415 self.join().await;
416
417 // Now check the state again
418 if let Some(panic_msg) = &self.panic_message {
419 if self.is_callback_panic {
420 State::CallbackPanicked(panic_msg.clone())
421 } else {
422 State::TaskPanicked(panic_msg.clone())
423 }
424 } else if self.is_ready() {
425 State::Completed
426 } else {
427 // This shouldn't happen
428 State::Pending
429 }
430 } else if self.is_ready() {
431 State::Completed
432 } else {
433 State::Pending
434 }
435 } else {
436 State::NotInitialized
437 }
438 }
439 /// Attempts to retrieve the result of the computation if available.
440 ///
441 /// Returns `Some(&T)` if the task has completed successfully, or `None` if the task
442 /// is still pending, panicked, or not started.
443 ///
444 /// This is a non-blocking operation that returns immediately.
445 ///
446 /// # Examples
447 ///
448 /// ```rust
449 /// use async_deferred::Deferred;
450 /// # tokio_test::block_on(async {
451 /// let deferred = Deferred::start(|| async { 42 });
452 ///
453 /// // Might return None if task hasn't finished yet
454 /// if let Some(result) = deferred.try_get() {
455 /// println!("Result: {}", result);
456 /// }
457 /// # })
458 /// ```
459 pub fn try_get(&self) -> Option<&T> {
460 self.value.get()
461 }
462
463 /// Waits for the task to complete and returns a reference to self.
464 ///
465 /// If the task is still pending, this will await its completion (either success or panic).
466 /// If the task has already completed or panicked, this returns immediately.
467 ///
468 /// This method allows for method chaining: `deferred.join().await.try_get()`.
469 ///
470 /// # Examples
471 ///
472 /// ```rust
473 /// use async_deferred::Deferred;
474 ///
475 /// # tokio_test::block_on(async {
476 /// let mut deferred = Deferred::start(|| async {
477 /// tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
478 /// 42
479 /// });
480 ///
481 /// // Wait for completion and get result
482 /// let result = deferred.join().await.try_get();
483 /// assert_eq!(result, Some(&42));
484 /// # })
485 /// ```
486 pub async fn join(&mut self) -> &Self {
487 if let Some(handle) = std::mem::take(&mut self.task_handle) {
488 let result = handle.await;
489 match result {
490 Ok(_) => {
491 // Task completed successfully
492 },
493 Err(join_err) => {
494 // Check if it's a callback panic and extract message
495 let (panic_msg, is_callback_panic) = if join_err.is_panic() {
496 if let Ok(panic_payload) = join_err.try_into_panic() {
497 let panic_msg = if let Some(s) = panic_payload.downcast_ref::<&str>() {
498 format!("Panic message: {}", s)
499 } else if let Some(s) = panic_payload.downcast_ref::<String>() {
500 format!("Panic message: {}", s)
501 } else {
502 "Panic occurred, but couldn't get the message.".to_string()
503 };
504
505 (panic_msg, self.is_ready())
506 } else {
507 ("Panic occurred, but couldn't extract panic info.".to_string(), false)
508 }
509 } else if join_err.is_cancelled() {
510 ("Task was cancelled.".to_string(), false)
511 } else {
512 ("Unknown join error.".to_string(), false)
513 };
514
515 self.panic_message = Some(panic_msg);
516 self.is_callback_panic = is_callback_panic;
517 }
518 }
519 }
520 self
521 }
522
523 /// Cancels the current task if it's pending.
524 ///
525 /// If the task is not pending (completed, panicked, or not initialized),
526 /// this method does nothing and returns `false`. Returns `true` if the
527 /// task was successfully cancelled.
528 ///
529 /// After cancellation, the `Deferred` returns to the `NotInitialized` state
530 /// and can be reused with a new task via `begin()` or `begin_with_callback()`.
531 ///
532 /// # Returns
533 /// - `true` if a pending task was cancelled
534 /// - `false` if there was no pending task to cancel
535 ///
536 /// # Examples
537 ///
538 /// ```rust
539 /// use async_deferred::{Deferred, State};
540 ///
541 /// # tokio_test::block_on(async {
542 /// let mut deferred = Deferred::start(|| async {
543 /// tokio::time::sleep(tokio::time::Duration::from_secs(10)).await;
544 /// 42
545 /// });
546 ///
547 /// let was_cancelled = deferred.cancel();
548 /// assert!(was_cancelled);
549 /// assert_eq!(deferred.state(), State::NotInitialized);
550 ///
551 /// // Can reuse the deferred after cancellation
552 /// deferred.begin(|| async { 100 });
553 /// assert!(deferred.is_pending());
554 /// # })
555 /// ```
556 ///
557 /// ```rust
558 /// use async_deferred::{Deferred, State};
559 ///
560 /// # tokio_test::block_on(async {
561 /// // Task completes quickly
562 /// let mut deferred = Deferred::start(|| async { 42 });
563 /// tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
564 ///
565 /// // Try to cancel after completion - does nothing
566 /// let was_cancelled = deferred.cancel();
567 /// assert!(!was_cancelled);
568 /// assert_eq!(deferred.state(), State::Completed);
569 /// assert_eq!(deferred.take(), Some(42));
570 /// # })
571 /// ```
572 ///
573 /// ```rust
574 /// use async_deferred::{Deferred, State};
575 ///
576 /// # tokio_test::block_on(async {
577 /// // Not initialized yet
578 /// let mut deferred: Deferred<i32> = Deferred::new();
579 ///
580 /// // Try to cancel uninitialized task - does nothing
581 /// let was_cancelled = deferred.cancel();
582 /// assert!(!was_cancelled);
583 /// assert_eq!(deferred.state(), State::NotInitialized);
584 /// # })
585 /// ```
586 pub fn cancel(&mut self) -> bool{
587 if self.is_pending() {
588 if let Some(handle) = &self.task_handle {
589 handle.abort();
590 }
591 // Reset to uninitialized state
592 self.task_handle = None;
593 self.value = Arc::new(OnceCell::new());
594 self.panic_message = None;
595 self.is_callback_panic = false;
596 true
597 } else {
598 false
599 }
600 }
601
602 /// Attempts to take ownership of the computed value.
603 ///
604 /// Returns `Some(T)` if the task has completed successfully, consuming the stored result.
605 /// Returns `None` if the task is still pending, panicked, or not started.
606 ///
607 /// After calling this method successfully, subsequent calls will return `None` since
608 /// the value has been moved out.
609 ///
610 /// # Examples
611 ///
612 /// ```rust
613 /// use async_deferred::Deferred;
614 ///
615 /// # tokio_test::block_on(async {
616 /// let mut deferred = Deferred::start(|| async { vec![1, 2, 3] });
617 ///
618 /// // Wait for completion
619 /// deferred.join().await;
620 ///
621 /// // Take ownership of the result
622 /// let result = deferred.take();
623 /// assert_eq!(result, Some(vec![1, 2, 3]));
624 ///
625 /// // Subsequent calls return None
626 /// assert_eq!(deferred.take(), None);
627 /// # })
628 /// ```
629 ///
630 /// [`take`](Self::take) will not consume if it is still pending
631 /// ```rust
632 /// use async_deferred::Deferred;
633 ///
634 /// # tokio_test::block_on(async {
635 /// let mut deferred = Deferred::start(|| async {
636 /// tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
637 /// 42
638 /// });
639 /// // If still pending, doesn't consume it
640 /// assert_eq!(deferred.take(), None);
641 /// tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
642 /// assert!(matches!(deferred.try_get(), Some(42)));
643 /// # })
644 /// ```
645 ///
646 pub fn take(&mut self) -> Option<T> {
647 if self.is_ready() {
648 let value = std::mem::take(&mut self.value);
649 self.task_handle = None;
650 Arc::try_unwrap(value).ok()?.into_inner()
651 } else {
652 None
653 }
654 }
655
656
657 /// Returns `true` if the task panicked during execution.
658 ///
659 /// A task is considered panicked if it was started but the `JoinHandle` indicates
660 /// it finished without storing a result in the `OnceCell`.
661 ///
662 /// # Examples
663 ///
664 /// ```rust
665 /// use async_deferred::Deferred;
666 ///
667 /// # tokio_test::block_on(async {
668 /// let mut deferred = Deferred::start(|| async {
669 /// panic!("Something went wrong!");
670 /// });
671 ///
672 /// tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
673 ///
674 /// assert!(deferred.has_task_panicked());
675 /// # })
676 /// ```
677 pub fn has_task_panicked(&self) -> bool {
678 matches!(self.state(), State::TaskPanicked(_))
679 }
680
681
682 /// Returns `true` if the data is available.
683 ///
684 /// # Examples
685 ///
686 /// ```rust
687 /// use async_deferred::Deferred;
688 ///
689 /// # tokio_test::block_on(async {
690 /// let mut deferred = Deferred::start(|| async {
691 /// tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
692 /// 42
693 /// });
694 ///
695 /// // Initially not ready
696 /// assert!(!deferred.is_ready());
697 ///
698 /// deferred.join().await;
699 /// assert!(deferred.is_ready());
700 /// # })
701 /// ```
702 pub fn is_ready(&self) -> bool {
703 self.value.get().is_some()
704 }
705
706 /// Returns `true` if the task has completed successfully.
707 ///
708 /// This means the computation finished without panicking and a result is available
709 /// via [`try_get`](Self::try_get) or [`take`](Self::take).
710 ///
711 /// # Examples
712 ///
713 /// ```rust
714 /// use async_deferred::Deferred;
715 ///
716 /// # tokio_test::block_on(async {
717 /// let mut deferred = Deferred::start(|| async {
718 /// tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
719 /// 42
720 /// });
721 ///
722 /// // Initially not ready
723 /// assert!(!deferred.is_complete());
724 ///
725 /// deferred.join().await;
726 /// println!("{:?}", deferred.state());
727 /// assert!(deferred.is_complete());
728 /// # })
729 pub fn is_complete(&self) -> bool {
730 matches!(self.state(), State::Completed)
731 }
732
733 /// Returns `true` if the task is currently running.
734 ///
735 /// A task is pending if it has been started but hasn't completed or panicked yet.
736 ///
737 /// # Examples
738 ///
739 /// ```rust
740 /// use async_deferred::Deferred;
741 /// # tokio_test::block_on(async {
742 /// let deferred = Deferred::start(|| async {
743 /// tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
744 /// 42
745 /// });
746 ///
747 /// assert!(deferred.is_pending()); // Task is running
748 /// # })
749 /// ```
750 pub fn is_pending(&self) -> bool {
751 matches!(self.state(), State::Pending)
752 }
753
754 /// Returns `true` if the task hasn't been initialized yet.
755 ///
756 /// This is the initial state of a `Deferred` created with [`new`](Self::new).
757 ///
758 /// # Examples
759 ///
760 /// ```rust
761 /// use async_deferred::Deferred;
762 /// # tokio_test::block_on(async {
763 /// let deferred: Deferred<i32> = Deferred::new();
764 /// assert!(deferred.is_not_initialized());
765 ///
766 /// let started_deferred = Deferred::start(|| async { 42 });
767 /// assert!(!started_deferred.is_not_initialized());
768 /// # })
769 /// ```
770 pub fn is_not_initialized(&self) -> bool {
771 matches!(self.state(), State::NotInitialized)
772 }
773}
774
775impl<T> Default for Deferred<T>
776where
777 T: Send + Sync + 'static,
778{
779 /// Creates a new empty `Deferred` instance.
780 ///
781 /// Equivalent to [`Deferred::new()`](Self::new).
782 fn default() -> Self {
783 Self::new()
784 }
785}