louis_sys/
lib.rs

1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3
4use std::sync::atomic::{AtomicBool, Ordering};
5
6// Whether or not we (the -sys crate) hold the token right now.
7static HAVE_TOKEN : AtomicBool = AtomicBool::new(true);
8
9/// A token that can only ever exist once in the context of an entire process.
10/// This is needed since liblouis is inherently thread-unsafe.
11/// Safe abstractions over this crate have to guard all liblouis function calls,
12/// allowing them only if this token is held.
13/// Note that the token itself does not enable any safe calling of liblouis functions - higher-level bindings need to provide this.
14pub struct ThreadUnsafetyToken(());
15
16impl ThreadUnsafetyToken {
17    /// Tries to get an exclusive ThreadUnsafetyToken, returning it if successful and `None` otherwise.
18    pub fn take() -> Option<Self> {
19        if HAVE_TOKEN.swap(false, Ordering::SeqCst) {
20            Some(ThreadUnsafetyToken(()))
21        } else {
22            None
23        }
24    }
25}
26
27impl Drop for ThreadUnsafetyToken {
28    fn drop(&mut self) {
29        if HAVE_TOKEN.swap(true, Ordering::SeqCst) {
30            panic!("Tried to drop ThreadUnsafetyToken back but we're also holding one. Something is very wrong and UB is likely!")
31        } else {
32            ()
33        }
34    }
35}
36
37
38include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
39
40#[cfg(test)]
41mod tests;
42
43#[cfg(test)]
44#[macro_use]
45extern crate lazy_static;
46
47#[cfg(test)]
48extern crate semver_parser;