• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::cell::Cell;
6 
7 use thiserror::Error as ThisError;
8 
9 thread_local! (static EXECUTOR_ACTIVE: Cell<bool> = Cell::new(false));
10 
11 #[derive(ThisError, Debug)]
12 #[error("Nested execution is not supported")]
13 struct NestedExecutionNotSupported;
14 
15 #[derive(Debug)]
16 pub struct ExecutionGuard;
17 
18 impl Drop for ExecutionGuard {
drop(&mut self)19     fn drop(&mut self) {
20         EXECUTOR_ACTIVE.with(|active| {
21             assert!(active.get());
22             active.set(false);
23         })
24     }
25 }
26 
enter() -> anyhow::Result<ExecutionGuard>27 pub fn enter() -> anyhow::Result<ExecutionGuard> {
28     EXECUTOR_ACTIVE.with(|active| {
29         if active.get() {
30             Err(NestedExecutionNotSupported.into())
31         } else {
32             active.set(true);
33 
34             Ok(ExecutionGuard)
35         }
36     })
37 }
38 
39 #[cfg(test)]
40 mod test {
41     use crate::Executor;
42 
43     use super::NestedExecutionNotSupported;
44 
45     #[test]
nested_execution()46     fn nested_execution() {
47         Executor::new()
48             .run_until(async {
49                 let e = Executor::new()
50                     .run_until(async {})
51                     .expect_err("nested execution successful");
52                 e.downcast::<NestedExecutionNotSupported>()
53                     .expect("unexpected error type");
54             })
55             .unwrap();
56 
57         let ex = Executor::new();
58         ex.run_until(async {
59             let e = ex
60                 .run_until(async {})
61                 .expect_err("nested execution successful");
62             e.downcast::<NestedExecutionNotSupported>()
63                 .expect("unexpected error type");
64         })
65         .unwrap();
66     }
67 }
68