pylon_shimload/
runtime_impl.rs1use std::sync::{Mutex, OnceLock};
2
3use crate::{shim_loader, PylonError, PylonResult};
4
5#[derive(Debug)]
6struct RuntimeState {
7 leases: usize,
8 initialized: bool,
9}
10
11impl RuntimeState {
12 fn new() -> Self {
13 Self {
14 leases: 0,
15 initialized: false,
16 }
17 }
18}
19
20static RUNTIME_STATE: OnceLock<Mutex<RuntimeState>> = OnceLock::new();
21
22fn state() -> &'static Mutex<RuntimeState> {
23 RUNTIME_STATE.get_or_init(|| Mutex::new(RuntimeState::new()))
24}
25
26fn lock_state() -> std::sync::MutexGuard<'static, RuntimeState> {
27 match state().lock() {
28 Ok(guard) => guard,
29 Err(poisoned) => poisoned.into_inner(),
30 }
31}
32
33pub(crate) fn acquire_runtime() -> PylonResult<RuntimeLease> {
34 let mut st = lock_state();
35 if !st.initialized {
36 let shim = shim_loader::shim_or_err()?;
37 unsafe { (shim.pylon_initialize)() };
38 st.initialized = true;
39 }
40 st.leases += 1;
41 Ok(RuntimeLease { active: true })
42}
43
44fn release_runtime_internal() {
45 let mut st = lock_state();
46 if st.leases == 0 {
47 return;
48 }
49
50 st.leases -= 1;
51 if st.leases == 0 && st.initialized {
52 unsafe { (shim_loader::shim().pylon_terminate)(1) };
53 st.initialized = false;
54 }
55}
56
57pub(crate) fn runtime_version() -> PylonResult<crate::PylonVersion> {
58 let _lease = acquire_runtime()?;
59
60 let mut major = 0u32;
61 let mut minor = 0u32;
62 let mut subminor = 0u32;
63 let mut build = 0u32;
64
65 unsafe {
66 (shim_loader::shim().pylon_get_version)(&mut major, &mut minor, &mut subminor, &mut build)
67 };
68
69 Ok(crate::PylonVersion {
70 major,
71 minor,
72 subminor,
73 build,
74 })
75}
76
77pub fn shutdown() -> PylonResult<()> {
78 let mut st = lock_state();
79 if st.leases != 0 {
80 return Err(PylonError::Msg(
81 "Cannot shutdown runtime while handles are alive".to_string(),
82 ));
83 }
84 if st.initialized {
85 unsafe { (shim_loader::shim().pylon_terminate)(1) };
86 st.initialized = false;
87 }
88 Ok(())
89}
90
91pub struct RuntimeGuard {
96 _lease: RuntimeLease,
97}
98
99impl RuntimeGuard {
100 pub fn new() -> PylonResult<Self> {
101 Ok(Self {
102 _lease: acquire_runtime()?,
103 })
104 }
105}
106
107pub(crate) struct RuntimeLease {
108 active: bool,
109}
110
111impl Clone for RuntimeLease {
112 fn clone(&self) -> Self {
113 if self.active {
114 let mut st = lock_state();
115 st.leases += 1;
116 }
117 Self {
118 active: self.active,
119 }
120 }
121}
122
123impl Drop for RuntimeLease {
124 fn drop(&mut self) {
125 if self.active {
126 self.active = false;
127 release_runtime_internal();
128 }
129 }
130}