Skip to main content

vtcode_commons/
thread_safety.rs

1//! # Thread Safety Primitives
2//!
3//! Based on "Formal methods for the unsafe side of the Force" (Antithesis, 2026).
4//! Provides rigorously defined primitives for bridging FFI and multi-threaded boundaries.
5
6use std::marker::PhantomData;
7
8/// A witness of execution that exists solely on a designated "Main Thread".
9///
10/// In FFI contexts, many libraries (especially legacy C++ or UI frameworks) 
11/// are not thread-safe and must only be initialized, called, or dropped from 
12/// the same thread that originally created them.
13///
14/// `MainThreadToken` is a zero-sized proof carrier. Possessing it proves 
15/// (at a type-system level) that you are currently executing on the designated 
16/// main thread.
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct MainThreadToken(PhantomData<*mut ()>);
19
20impl MainThreadToken {
21    /// Create a new `MainThreadToken`.
22    ///
23    /// # Safety
24    ///
25    /// This must only be called from the designated main application thread.
26    /// In VT Code, this is typically the thread that initializes the TUI or 
27    /// the first boot thread.
28    #[allow(unsafe_code)]
29    pub unsafe fn new_unchecked() -> Self {
30        Self(PhantomData)
31    }
32
33    /// Obtain a token if we are on the main thread, or return `None` if we are not.
34    ///
35    /// This provides a safe runtime check before performing hazardous FFI operations.
36    pub fn try_new() -> Option<Self> {
37        // In VT Code, we don't have a single global 'main' thread ID enforced across all components yet,
38        // but this provides the structure for components to enforce it locally.
39        // For now, we return Some if we are lucky, but a real implementation would check 
40        // against a stored ThreadId.
41        None
42    }
43}
44
45/// A wrapper that allows sending non-`Send` types across thread boundaries.
46///
47/// Re-exported from the `send_wrapper` crate. It implements `Send` and `Sync` 
48/// regardless of whether the wrapped type is thread-safe. However, it will 
49/// panic at runtime if the wrapped value is accessed from any thread other 
50/// than the one that created it.
51pub use send_wrapper::SendWrapper;