Skip to main content

clt_database/turso_sdk_kit/src/
lib.rs

1use std::sync::atomic::{AtomicU32, Ordering};
2
3use crate::turso_sdk_kit::rsapi::TursoError;
4
5pub mod capi;
6pub mod rsapi;
7
8#[macro_export]
9macro_rules! assert_send {
10    ($($ty:ty),+ $(,)?) => {
11        const _: fn() = || {
12            fn check<T: Send>() {}
13            $( check::<$ty>(); )+
14        };
15    };
16}
17
18#[macro_export]
19macro_rules! assert_sync {
20    ($($ty:ty),+ $(,)?) => {
21        const _: fn() = || {
22            fn check<T: Sync>() {}
23            $( check::<$ty>(); )+
24        };
25    };
26}
27
28/// simple helper which return MISUSE error in case of concurrent access to some operation
29struct ConcurrentGuard {
30    in_use: AtomicU32,
31}
32
33struct ConcurrentGuardToken<'a> {
34    guard: &'a ConcurrentGuard,
35}
36
37impl ConcurrentGuard {
38    pub fn new() -> Self {
39        Self {
40            in_use: AtomicU32::new(0),
41        }
42    }
43    pub fn try_use(&self) -> Result<ConcurrentGuardToken<'_>, TursoError> {
44        if self
45            .in_use
46            .compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst)
47            .is_err()
48        {
49            return Err(TursoError::Misuse("concurrent use forbidden".to_string()));
50        };
51        Ok(ConcurrentGuardToken { guard: self })
52    }
53}
54
55impl<'a> Drop for ConcurrentGuardToken<'a> {
56    fn drop(&mut self) {
57        let before = self.guard.in_use.swap(0, Ordering::SeqCst);
58        assert!(
59            before == 1,
60            "invalid db state: guard wasn't in use while token is active"
61        );
62    }
63}
64
65pub use crate::{assert_send, assert_sync};