Skip to content

Commit addced2

Browse files
committed
Refactor resources
- Move storage of "Type->NIF Resource Type Handle" to a OnceLock map to allow implementing resource types without resorting to dynamic trait implementations - Add direct access methods to get an immutable reference to the wrapped objects - Add corresponding converters - Add monitor resource implementation - Require explicit trait implementation (not when using the existing macro for compatibility) - Allow implementing a "destructor" function that runs just before `Drop` but has access to the caller environment
1 parent 7fef3c5 commit addced2

File tree

22 files changed

+720
-382
lines changed

22 files changed

+720
-382
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,19 @@ versions.
1212

1313
### Added
1414

15+
- Resource type registration has been refactored to eventually remove the
16+
`rustler::resource!` macro (#617, necessary due to a pending deprecation of a
17+
Rust feature, #606)
18+
- Resources can now explicitly implement the new `Resource` trait and provide a
19+
custom `destructor` function that is run before `drop` and receives an `Env`
20+
parameter (#617)
21+
- Process monitoring via resources can now be used on resource types that
22+
implement the `MonitorResource` trait (#617)
23+
1524
### Fixed
1625

26+
- Unwinding in the `on_load` callback is now caught and leads to a panic (#617)
27+
1728
### Changed
1829

1930
- NIF implementations are now discovered automatically and the respective

UPGRADE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ This document is intended to simplify upgrading to newer versions by extending t
1010
2. The functionality related to the `derive` feature is now unconditionally
1111
active. The feature flag is kept for compatibility for now but will be
1212
removed in the future.
13+
3. To register a type as a resource, the new `#[derive(Resource)]` can be used
14+
now. It is implicitly registered and does not require (or work in) the old
15+
explicit registration with `rustler::resource!` a custom `load` function.
1316

1417
## 0.32 -> 0.33
1518

rustler/src/codegen_runtime.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub use inventory;
1212
pub use crate::wrapper::exception::raise_exception;
1313
pub use crate::wrapper::{
1414
c_char, c_int, c_uint, c_void, get_nif_resource_type_init_size, DEF_NIF_ENTRY, DEF_NIF_FUNC,
15-
MUTABLE_NIF_RESOURCE_HANDLE, NIF_ENV, NIF_MAJOR_VERSION, NIF_MINOR_VERSION, NIF_TERM,
15+
NIF_ENV, NIF_MAJOR_VERSION, NIF_MINOR_VERSION, NIF_TERM,
1616
};
1717

1818
#[cfg(windows)]
@@ -100,15 +100,12 @@ impl fmt::Debug for NifReturned {
100100
/// # Unsafe
101101
///
102102
/// This takes arguments, including raw pointers, that must be correct.
103-
pub unsafe fn handle_nif_init_call(
104-
function: Option<for<'a> fn(Env<'a>, Term<'a>) -> bool>,
105-
r_env: NIF_ENV,
106-
load_info: NIF_TERM,
103+
pub unsafe fn handle_nif_init_call<'a>(
104+
function: for<'b> fn(Env<'b>, Term<'b>) -> bool,
105+
env: Env<'a>,
106+
load_info: Term<'a>,
107107
) -> c_int {
108-
let env = Env::new(&(), r_env);
109-
let term = Term::new(env, load_info);
110-
111-
function.map_or(0, |inner| i32::from(!inner(env, term)))
108+
std::panic::catch_unwind(|| function(env, load_info)).map_or(1, |x| i32::from(!x))
112109
}
113110

114111
pub fn handle_nif_result<T>(

rustler/src/env.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::thread::is_scheduler_thread;
12
use crate::types::LocalPid;
23
use crate::wrapper::{NIF_ENV, NIF_TERM};
34
use crate::{Encoder, Term};
@@ -17,6 +18,7 @@ type EnvId<'a> = PhantomData<*mut &'a u8>;
1718
/// There is no way to allocate a Env at the moment, but this may be possible in the future.
1819
#[derive(Clone, Copy)]
1920
pub struct Env<'a> {
21+
pub(crate) init: bool,
2022
env: NIF_ENV,
2123
id: EnvId<'a>,
2224
}
@@ -47,11 +49,19 @@ impl<'a> Env<'a> {
4749
/// Don't create multiple `Env`s with the same lifetime.
4850
pub unsafe fn new<T>(_lifetime_marker: &'a T, env: NIF_ENV) -> Env<'a> {
4951
Env {
52+
init: false,
5053
env,
5154
id: PhantomData,
5255
}
5356
}
5457

58+
#[doc(hidden)]
59+
pub unsafe fn new_init_env<T>(_lifetime_marker: &'a T, env: NIF_ENV) -> Env<'a> {
60+
let mut res = Self::new(_lifetime_marker, env);
61+
res.init = true;
62+
res
63+
}
64+
5565
pub fn as_c_arg(self) -> NIF_ENV {
5666
self.env
5767
}
@@ -229,7 +239,7 @@ impl OwnedEnv {
229239
F: FnOnce(Env<'a>) -> T,
230240
T: Encoder,
231241
{
232-
if unsafe { rustler_sys::enif_thread_type() } != rustler_sys::ERL_NIF_THR_UNDEFINED {
242+
if is_scheduler_thread() {
233243
panic!("send_and_clear: current thread is managed");
234244
}
235245

rustler/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ pub use crate::types::{
4545
#[cfg(feature = "big_integer")]
4646
pub use crate::types::BigInt;
4747

48-
pub mod resource;
49-
pub use crate::resource::ResourceArc;
48+
mod resource;
49+
pub use crate::resource::{Monitor, Resource, ResourceArc, ResourceInitError};
5050

5151
#[doc(hidden)]
5252
pub mod dynamic;

0 commit comments

Comments
 (0)