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>27pub 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