Skip to content

Commit

Permalink
Update boxroot (#160)
Browse files Browse the repository at this point in the history
* chore: update boxroot bindings

* cleanup: additional improvements for boxroot changes

* cleanup: remove explicit call to caml_thread_initialize

* cleanup: remove empty declaration

* cleanup: remove caml_thread_initialize from ocaml-sys

* chore: use boxroot 0.4.0

* cleanup: improve panic handler implementation

* fix: no-std
  • Loading branch information
zshipko authored Feb 6, 2025
1 parent a1016f8 commit abb3e13
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 51 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ features = [ "derive", "without-ocamlopt", "ocaml5" ]

[dependencies]
ocaml-sys = {path = "./sys", version = ">=0.25"}
ocaml-boxroot-sys = {version = "0.3.1", default-features = false}
ocaml-boxroot-sys = {version = "0.4.0", default-features = false}
ocaml-derive = {path = "./derive", optional = true, version = "^1.0.0"}
cstr_core = {version = "0.2", optional = true}
ndarray = {version = "^0.16.1", optional = true}
Expand Down
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,6 @@ pub use crate::tag::Tag;
pub use crate::types::{bigarray, Array, List, Seq};
pub use crate::value::{FromValue, Raw, ToValue, Value};

pub use crate::macros::initial_setup;

/// OCaml `float`
pub type Float = f64;

Expand Down
39 changes: 1 addition & 38 deletions src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,3 @@
static PANIC_HANDLER_INIT: core::sync::atomic::AtomicBool =
core::sync::atomic::AtomicBool::new(false);

#[doc(hidden)]
pub fn initial_setup() {
if PANIC_HANDLER_INIT
.compare_exchange(
false,
true,
core::sync::atomic::Ordering::Relaxed,
core::sync::atomic::Ordering::Relaxed,
)
.is_err()
{
return;
}

#[cfg(not(feature = "no-panic-hook"))]
{
::std::panic::set_hook(Box::new(|info| {
let err = info.payload();
let msg = if err.is::<&str>() {
err.downcast_ref::<&str>().unwrap().to_string()
} else if err.is::<String>() {
err.downcast_ref::<String>().unwrap().clone()
} else {
format!("{:?}", err)
};

crate::Error::raise_failure(&msg)
}))
}
}

/// `body!` is needed to help the OCaml runtime to manage garbage collection, it should
/// be used to wrap the body of each function exported to OCaml. Panics from Rust code
/// will automatically be unwound/caught here (unless the `no-std` feature is enabled)
Expand All @@ -49,10 +15,7 @@ pub fn initial_setup() {
#[macro_export]
macro_rules! body {
($gc:ident: $code:block) => {{
let $gc = unsafe { $crate::Runtime::recover_handle() };

// Ensure panic handler is initialized
$crate::initial_setup();
let $gc = unsafe { &$crate::Runtime::init() };

{
$code
Expand Down
65 changes: 58 additions & 7 deletions src/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// OCaml runtime handle
pub struct Runtime {
_private: (),
_panic_guard: PanicGuard,
}

static RUNTIME_INIT: core::sync::atomic::AtomicBool = core::sync::atomic::AtomicBool::new(false);
Expand All @@ -9,7 +9,9 @@ impl Runtime {
/// Initialize the OCaml runtime.
pub fn init() -> Self {
Self::init_persistent();
Self { _private: () }
Self {
_panic_guard: PanicGuard::new(),
}
}

/// Initializes the OCaml runtime.
Expand Down Expand Up @@ -44,7 +46,9 @@ impl Runtime {
#[doc(hidden)]
#[inline(always)]
pub unsafe fn recover_handle() -> &'static Self {
static RUNTIME: Runtime = Runtime { _private: () };
static RUNTIME: Runtime = Runtime {
_panic_guard: PanicGuard,
};
&RUNTIME
}

Expand All @@ -62,15 +66,12 @@ impl Runtime {
/// Initialize the OCaml runtime, the runtime will be
/// freed when the value goes out of scope
pub fn init() -> Runtime {
let rt = Runtime::init();
crate::initial_setup();
rt
Runtime::init()
}

/// Initialize the OCaml runtime
pub fn init_persistent() {
Runtime::init_persistent();
crate::initial_setup();
}

/// Wrapper for `caml_leave_blocking_section`
Expand Down Expand Up @@ -104,3 +105,53 @@ pub unsafe fn gc_full_major() {
pub unsafe fn gc_compact() {
ocaml_sys::caml_gc_compaction(ocaml_sys::UNIT);
}

#[cfg(not(feature = "no-std"))]
thread_local! {
#[allow(clippy::missing_const_for_thread_local)]
static GUARD_COUNT: core::cell::Cell<usize> = const { core::cell::Cell::new(0) };
}

#[cfg(not(feature = "no-std"))]
static INIT: std::sync::Once = std::sync::Once::new();

struct PanicGuard;

impl PanicGuard {
#[cfg(not(any(feature = "no-panic-hook", feature = "no-std")))]
pub(crate) fn new() -> Self {
INIT.call_once(|| {
let original_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |panic_info| {
if GUARD_COUNT.with(|count| count.get()) > 0 {
let err = panic_info.payload();
let msg = if let Some(s) = err.downcast_ref::<&str>() {
s.to_string()
} else if let Some(s) = err.downcast_ref::<String>() {
s.clone()
} else {
format!("{:?}", err)
};
crate::Error::raise_failure(&msg);
} else {
original_hook(panic_info);
}
}));
});

GUARD_COUNT.with(|count| count.set(count.get() + 1));
PanicGuard
}

#[cfg(any(feature = "no-panic-hook", feature = "no-std"))]
pub(crate) fn new() -> Self {
PanicGuard
}
}

#[cfg(not(any(feature = "no-panic-hook", feature = "no-std")))]
impl Drop for PanicGuard {
fn drop(&mut self) {
GUARD_COUNT.with(|count| count.set(count.get() - 1));
}
}
4 changes: 1 addition & 3 deletions sys/src/ocaml-sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,4 @@ void caml_sys_store_double_field(value x, mlsize_t index, double d) {
Store_double_field(x, index, d);
}

caml_domain_state* caml_sys_get_domain_state() {
return Caml_state;
}
caml_domain_state *caml_sys_get_domain_state() { return Caml_state; }
1 change: 1 addition & 0 deletions sys/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extern "C" {
pub fn caml_named_value(name: *const Char) -> *const Value;
pub fn caml_enter_blocking_section();
pub fn caml_leave_blocking_section();
pub fn caml_thread_initialize(unit: Value) -> Value;
}

// GC control
Expand Down

0 comments on commit abb3e13

Please sign in to comment.