lora-ruby 0.5.6 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/src/gvl.rs ADDED
@@ -0,0 +1,55 @@
1
+ //! Global VM Lock release primitive.
2
+
3
+ use std::ffi::c_void;
4
+ use std::mem::MaybeUninit;
5
+
6
+ /// Run `f` with Ruby's Global VM Lock released.
7
+ ///
8
+ /// Semantics match `rb_thread_call_without_gvl` — other Ruby threads can
9
+ /// progress while `f` runs. The closure MUST NOT touch Ruby state (no
10
+ /// `Value`s, no allocations into the Ruby heap), which we arrange by
11
+ /// keeping all such work on the calling thread. Everything inside
12
+ /// `database_execute`'s closure is pure Rust on pre-extracted data, so
13
+ /// this is sound.
14
+ pub(crate) fn without_gvl<F, R>(f: F) -> R
15
+ where
16
+ F: FnOnce() -> R,
17
+ F: Send,
18
+ R: Send,
19
+ {
20
+ struct Data<F, R> {
21
+ func: Option<F>,
22
+ result: MaybeUninit<R>,
23
+ }
24
+
25
+ unsafe extern "C" fn trampoline<F, R>(data: *mut c_void) -> *mut c_void
26
+ where
27
+ F: FnOnce() -> R,
28
+ {
29
+ let data = &mut *(data as *mut Data<F, R>);
30
+ let f = data
31
+ .func
32
+ .take()
33
+ .expect("without_gvl: closure already taken");
34
+ data.result.write(f());
35
+ std::ptr::null_mut()
36
+ }
37
+
38
+ let mut data = Data::<F, R> {
39
+ func: Some(f),
40
+ result: MaybeUninit::uninit(),
41
+ };
42
+
43
+ unsafe {
44
+ rb_sys::rb_thread_call_without_gvl(
45
+ Some(trampoline::<F, R>),
46
+ &mut data as *mut _ as *mut c_void,
47
+ // No unblock function — the engine doesn't implement
48
+ // cooperative cancellation, and a forced longjmp out of a
49
+ // mutex-holding section would be worse than waiting.
50
+ None,
51
+ std::ptr::null_mut(),
52
+ );
53
+ data.result.assume_init()
54
+ }
55
+ }