1use std::{
4 future::Future,
5 sync::{Arc, atomic::AtomicU32},
6};
7
8use tokio::{
9 task::{JoinHandle, futures::TaskLocalFuture},
10 task_local,
11};
12
13#[derive(Debug)]
15pub struct CompilerContext {
16 dependenc_id_generator: AtomicU32,
17}
18
19task_local! {
20 pub static CURRENT_COMPILER_CONTEXT: Arc<CompilerContext>;
22}
23#[allow(clippy::new_without_default)]
24impl CompilerContext {
25 pub fn new() -> Self {
26 Self {
27 dependenc_id_generator: AtomicU32::new(0),
28 }
29 }
30 pub fn fetch_new_dependency_id(&self) -> u32 {
31 self
32 .dependenc_id_generator
33 .fetch_add(1, std::sync::atomic::Ordering::SeqCst)
34 }
35 pub fn dependency_id(&self) -> u32 {
36 self
37 .dependenc_id_generator
38 .load(std::sync::atomic::Ordering::SeqCst)
39 }
40 pub fn set_dependency_id(&self, id: u32) {
41 self
42 .dependenc_id_generator
43 .store(id, std::sync::atomic::Ordering::SeqCst);
44 }
45}
46
47pub fn fetch_new_dependency_id() -> u32 {
48 CURRENT_COMPILER_CONTEXT.get().fetch_new_dependency_id()
49}
50pub fn get_current_dependency_id() -> u32 {
51 CURRENT_COMPILER_CONTEXT.get().dependency_id()
52}
53pub fn set_current_dependency_id(id: u32) {
54 CURRENT_COMPILER_CONTEXT.get().set_dependency_id(id);
55}
56
57pub fn within_compiler_context<F>(
58 compiler_context: Arc<CompilerContext>,
59 f: F,
60) -> TaskLocalFuture<Arc<CompilerContext>, F>
61where
62 F: Future,
63{
64 CURRENT_COMPILER_CONTEXT.scope(compiler_context, f)
65}
66pub fn within_compiler_context_sync<F, R>(compiler_context: Arc<CompilerContext>, f: F) -> R
67where
68 F: FnOnce() -> R,
69{
70 CURRENT_COMPILER_CONTEXT.sync_scope(compiler_context, f)
71}
72
73pub fn within_compiler_context_for_testing_sync<F, R>(f: F) -> R
76where
77 F: FnOnce() -> R,
78{
79 CURRENT_COMPILER_CONTEXT.sync_scope(Arc::new(CompilerContext::new()), f)
80}
81pub fn within_compiler_context_for_testing<F>(f: F) -> TaskLocalFuture<Arc<CompilerContext>, F>
83where
84 F: Future,
85{
86 CURRENT_COMPILER_CONTEXT.scope(Arc::new(CompilerContext::new()), f)
87}
88
89pub fn spawn_in_compiler_context<F>(future: F) -> JoinHandle<F::Output>
90where
91 F: Future + Send + 'static,
92 F::Output: Send + 'static,
93{
94 let compiler_context = CURRENT_COMPILER_CONTEXT.get().clone();
95
96 tokio::spawn(CURRENT_COMPILER_CONTEXT.scope(compiler_context, future))
97}