]> git.proxmox.com Git - rustc.git/blob - vendor/futures-executor/src/enter.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / vendor / futures-executor / src / enter.rs
1 use std::cell::Cell;
2 use std::fmt;
3
4 thread_local!(static ENTERED: Cell<bool> = Cell::new(false));
5
6 /// Represents an executor context.
7 ///
8 /// For more details, see [`enter` documentation](enter()).
9 pub struct Enter {
10 _priv: (),
11 }
12
13 /// An error returned by `enter` if an execution scope has already been
14 /// entered.
15 pub struct EnterError {
16 _priv: (),
17 }
18
19 impl fmt::Debug for EnterError {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 f.debug_struct("EnterError").finish()
22 }
23 }
24
25 impl fmt::Display for EnterError {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 write!(f, "an execution scope has already been entered")
28 }
29 }
30
31 impl std::error::Error for EnterError {}
32
33 /// Marks the current thread as being within the dynamic extent of an
34 /// executor.
35 ///
36 /// Executor implementations should call this function before beginning to
37 /// execute a tasks, and drop the returned [`Enter`](Enter) value after
38 /// completing task execution:
39 ///
40 /// ```
41 /// use futures::executor::enter;
42 ///
43 /// let enter = enter().expect("...");
44 /// /* run task */
45 /// drop(enter);
46 /// ```
47 ///
48 /// Doing so ensures that executors aren't
49 /// accidentally invoked in a nested fashion.
50 ///
51 /// # Error
52 ///
53 /// Returns an error if the current thread is already marked, in which case the
54 /// caller should panic with a tailored error message.
55 pub fn enter() -> Result<Enter, EnterError> {
56 ENTERED.with(|c| {
57 if c.get() {
58 Err(EnterError { _priv: () })
59 } else {
60 c.set(true);
61
62 Ok(Enter { _priv: () })
63 }
64 })
65 }
66
67 impl fmt::Debug for Enter {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 f.debug_struct("Enter").finish()
70 }
71 }
72
73 impl Drop for Enter {
74 fn drop(&mut self) {
75 ENTERED.with(|c| {
76 assert!(c.get());
77 c.set(false);
78 });
79 }
80 }