Skip to content

[feat] mutex + fiber + thread + io || DRAFT #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 169 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
169 commits
Select commit Hold shift + click to select a range
5b0124c
[feat] mutex + fiber + thread + io
ms-jpq Jul 8, 2022
261a9d2
CI (AGP) - 2022-08-15 01:01
Aug 15, 2022
ed2e39e
CI (AGP) - 2022-08-16 01:06
Aug 16, 2022
2adb96a
CI (AGP) - 2022-08-17 01:04
Aug 17, 2022
bd34e70
CI (AGP) - 2022-08-18 01:08
Aug 18, 2022
1063358
CI (AGP) - 2022-08-19 01:01
Aug 19, 2022
53bc5a9
CI (AGP) - 2022-08-20 00:57
Aug 20, 2022
8522f13
CI (AGP) - 2022-08-21 00:59
Aug 21, 2022
092858c
CI (AGP) - 2022-08-22 01:00
Aug 22, 2022
fc5f137
CI (AGP) - 2022-08-23 01:08
Aug 23, 2022
4eb361d
CI (AGP) - 2022-08-24 01:04
Aug 24, 2022
9a89efe
CI (AGP) - 2022-08-25 01:09
Aug 25, 2022
13abff1
CI (AGP) - 2022-08-26 01:04
Aug 26, 2022
c7b7d36
CI (AGP) - 2022-08-27 00:57
Aug 27, 2022
482c794
CI (AGP) - 2022-08-28 01:03
Aug 28, 2022
926e847
CI (AGP) - 2022-08-29 01:07
Aug 29, 2022
6ef3626
CI (AGP) - 2022-08-30 01:10
Aug 30, 2022
3dc24a3
CI (AGP) - 2022-08-31 01:13
Aug 31, 2022
18423e5
CI (AGP) - 2022-09-01 01:00
Sep 1, 2022
b2fb66d
CI (AGP) - 2022-09-02 01:02
Sep 2, 2022
66f539b
CI (AGP) - 2022-09-04 01:02
Sep 4, 2022
fc51e7a
CI (AGP) - 2022-09-05 01:14
Sep 5, 2022
f008157
CI (AGP) - 2022-09-06 01:07
Sep 6, 2022
6338563
CI (AGP) - 2022-09-07 01:10
Sep 7, 2022
68c490c
CI (AGP) - 2022-09-08 01:05
Sep 8, 2022
606e9cc
CI (AGP) - 2022-09-09 01:08
Sep 9, 2022
442c1ff
CI (AGP) - 2022-09-10 01:06
Sep 10, 2022
05a4fc6
CI (AGP) - 2022-09-11 01:08
Sep 11, 2022
dce599f
CI (AGP) - 2022-09-12 01:07
Sep 12, 2022
3eb3518
CI (AGP) - 2022-09-13 01:07
Sep 13, 2022
2c178f9
CI (AGP) - 2022-09-14 01:04
Sep 14, 2022
9e05cf2
CI (AGP) - 2022-09-15 01:10
Sep 15, 2022
ac20327
CI (AGP) - 2022-09-16 01:10
Sep 16, 2022
85ff03c
CI (AGP) - 2022-09-17 01:05
Sep 17, 2022
07a25f6
CI (AGP) - 2022-09-18 01:11
Sep 18, 2022
18f9a80
CI (AGP) - 2022-09-19 01:07
Sep 19, 2022
b09ed2e
CI (AGP) - 2022-09-20 01:09
Sep 20, 2022
f2c45f6
CI (AGP) - 2022-09-21 01:11
Sep 21, 2022
5f67029
CI (AGP) - 2022-09-22 01:06
Sep 22, 2022
079a522
CI (AGP) - 2022-09-23 01:13
Sep 23, 2022
f46b0cf
CI (AGP) - 2022-09-24 01:11
Sep 24, 2022
d9b95b7
CI (AGP) - 2022-09-25 01:06
Sep 25, 2022
a6944a6
CI (AGP) - 2022-09-26 01:08
Sep 26, 2022
277ba3c
CI (AGP) - 2022-09-27 01:11
Sep 27, 2022
fcbdcf5
CI (AGP) - 2022-09-28 01:10
Sep 28, 2022
f3b142a
CI (AGP) - 2022-09-29 01:15
Sep 29, 2022
473ef2e
CI (AGP) - 2022-09-30 01:28
Sep 30, 2022
2b1b7ad
CI (AGP) - 2022-10-01 01:23
Oct 1, 2022
9b0799e
CI (AGP) - 2022-10-02 01:18
Oct 2, 2022
1a54828
CI (AGP) - 2022-10-03 01:08
Oct 3, 2022
bb95663
CI (AGP) - 2022-10-04 01:16
Oct 4, 2022
9480a42
CI (AGP) - 2022-10-05 01:15
Oct 5, 2022
0ef9d1e
CI (AGP) - 2022-10-06 01:09
Oct 6, 2022
4a6240c
CI (AGP) - 2022-10-07 01:19
Oct 7, 2022
2d78c7d
CI (AGP) - 2022-10-08 01:03
Oct 8, 2022
75189f4
CI (AGP) - 2022-10-09 01:09
Oct 9, 2022
056f1c1
CI (AGP) - 2022-10-10 01:14
Oct 10, 2022
e6578e1
CI (AGP) - 2022-10-11 01:06
Oct 11, 2022
50bd75a
CI (AGP) - 2022-10-12 01:21
Oct 12, 2022
60e3342
CI (AGP) - 2022-10-13 01:12
Oct 13, 2022
9f8179c
CI (AGP) - 2022-10-14 01:21
Oct 14, 2022
b6d0eab
CI (AGP) - 2022-10-15 01:14
Oct 15, 2022
8233753
CI (AGP) - 2022-10-16 01:18
Oct 16, 2022
51d3e69
CI (AGP) - 2022-10-17 01:20
Oct 17, 2022
7774e27
CI (AGP) - 2022-10-18 01:14
Oct 18, 2022
3dbbe1d
CI (AGP) - 2022-10-19 01:14
Oct 19, 2022
27ebb5f
CI (AGP) - 2022-10-20 01:10
Oct 20, 2022
70c71f6
CI (AGP) - 2022-10-21 01:08
Oct 21, 2022
c15e2ed
CI (AGP) - 2022-10-22 01:16
Oct 22, 2022
8a01b90
CI (AGP) - 2022-10-23 01:12
Oct 23, 2022
84c30c7
CI (AGP) - 2022-10-24 01:23
Oct 24, 2022
c16ce94
CI (AGP) - 2022-10-25 01:20
Oct 25, 2022
c988cff
CI (AGP) - 2022-10-26 01:05
Oct 26, 2022
92555a4
CI (AGP) - 2022-10-27 01:05
Oct 27, 2022
6d898cd
CI (AGP) - 2022-10-28 01:10
Oct 28, 2022
90cac10
CI (AGP) - 2022-10-29 00:58
Oct 29, 2022
e8340b8
CI (AGP) - 2022-10-30 01:11
Oct 30, 2022
6a44e24
CI (AGP) - 2022-10-31 01:12
Oct 31, 2022
cbe26d1
CI (AGP) - 2022-11-01 01:16
Nov 1, 2022
4a55530
CI (AGP) - 2022-11-02 01:09
Nov 2, 2022
c0ffaa3
CI (AGP) - 2022-11-03 01:03
Nov 3, 2022
269fd5d
CI (AGP) - 2022-11-04 01:04
Nov 4, 2022
0332f2b
CI (AGP) - 2022-11-05 01:03
Nov 5, 2022
9a3df1e
CI (AGP) - 2022-11-06 01:02
Nov 6, 2022
8beaec8
CI (AGP) - 2022-11-07 00:59
Nov 7, 2022
eb1f3fd
CI (AGP) - 2022-11-08 01:00
Nov 8, 2022
d270692
CI (AGP) - 2022-11-09 01:02
Nov 9, 2022
539e6fc
CI (AGP) - 2022-11-10 01:01
Nov 10, 2022
d4b9918
CI (AGP) - 2022-11-11 01:04
Nov 11, 2022
1619ab9
CI (AGP) - 2022-11-12 01:00
Nov 12, 2022
942a4bc
CI (AGP) - 2022-11-13 00:59
Nov 13, 2022
e3c51b6
CI (AGP) - 2022-11-14 00:58
Nov 14, 2022
c787613
CI (AGP) - 2022-11-15 00:58
Nov 15, 2022
dd8e03e
CI (AGP) - 2022-11-16 00:59
Nov 16, 2022
d395704
CI (AGP) - 2022-11-17 00:58
Nov 17, 2022
33f33d3
CI (AGP) - 2022-11-18 01:01
Nov 18, 2022
42f70b9
CI (AGP) - 2022-11-19 00:59
Nov 19, 2022
fd7b69f
CI (AGP) - 2022-11-20 01:01
Nov 20, 2022
3070c28
CI (AGP) - 2022-11-21 00:59
Nov 21, 2022
e045b44
CI (AGP) - 2022-11-22 00:59
Nov 22, 2022
69c80c8
CI (AGP) - 2022-11-23 00:52
Nov 23, 2022
ac70c9f
CI (AGP) - 2022-11-24 00:58
Nov 24, 2022
7c20c9b
CI (AGP) - 2022-11-25 00:54
Nov 25, 2022
ff9848c
CI (AGP) - 2022-11-26 00:49
Nov 26, 2022
488fb68
CI (AGP) - 2022-11-27 00:57
Nov 27, 2022
a86102c
CI (AGP) - 2022-11-28 00:51
Nov 28, 2022
3cf634a
CI (AGP) - 2022-11-29 00:54
Nov 29, 2022
ab6307f
CI (AGP) - 2022-11-30 00:54
Nov 30, 2022
d4fb86c
CI (AGP) - 2022-12-01 00:59
Dec 1, 2022
6a53e33
CI (AGP) - 2022-12-02 00:51
Dec 2, 2022
62a33e8
CI (AGP) - 2022-12-03 00:47
Dec 3, 2022
4820b30
CI (AGP) - 2022-12-04 00:50
Dec 4, 2022
efe85e6
CI (AGP) - 2022-12-05 00:49
Dec 5, 2022
7f03842
CI (AGP) - 2022-12-06 00:48
Dec 6, 2022
5ba0279
CI (AGP) - 2022-12-07 00:52
Dec 7, 2022
124fdea
CI (AGP) - 2022-12-08 00:48
Dec 8, 2022
fa78592
CI (AGP) - 2022-12-09 00:51
Dec 9, 2022
d793b62
CI (AGP) - 2022-12-10 00:46
Dec 10, 2022
86d0401
CI (AGP) - 2022-12-11 00:55
Dec 11, 2022
dad0d67
CI (AGP) - 2022-12-12 00:52
Dec 12, 2022
bccac15
CI (AGP) - 2022-12-13 00:54
Dec 13, 2022
591255c
CI (AGP) - 2022-12-14 00:50
Dec 14, 2022
59791b7
CI (AGP) - 2022-12-15 00:52
Dec 15, 2022
d7d0244
CI (AGP) - 2022-12-16 00:49
Dec 16, 2022
2c1c4bb
CI (AGP) - 2022-12-17 00:44
Dec 17, 2022
36b2b1a
CI (AGP) - 2022-12-18 00:46
Dec 18, 2022
693b318
CI (AGP) - 2022-12-19 00:44
Dec 19, 2022
85ef3e4
CI (AGP) - 2022-12-20 00:50
Dec 20, 2022
99500a8
CI (AGP) - 2022-12-21 00:44
Dec 21, 2022
d2f6dd1
CI (AGP) - 2022-12-22 00:48
Dec 22, 2022
bfd37fa
CI (AGP) - 2022-12-23 00:47
Dec 23, 2022
f03f687
CI (AGP) - 2022-12-25 01:01
Dec 25, 2022
a13fa4a
CI (AGP) - 2023-01-08 01:04
Jan 8, 2023
385b8ec
CI (AGP) - 2023-01-15 01:04
Jan 15, 2023
a71222c
CI (AGP) - 2023-01-22 01:04
Jan 22, 2023
a6718a0
CI (AGP) - 2023-01-29 01:06
Jan 29, 2023
71bd137
CI (AGP) - 2023-02-05 01:06
Feb 5, 2023
6b988b3
CI (AGP) - 2023-02-12 01:06
Feb 12, 2023
c1b5798
CI (AGP) - 2023-02-19 01:05
Feb 19, 2023
b0b1e66
CI (AGP) - 2023-02-26 01:10
Feb 26, 2023
16d8e0b
CI (AGP) - 2023-03-05 01:12
Mar 5, 2023
88e29be
CI (AGP) - 2023-03-12 01:06
Mar 12, 2023
722b4fb
CI (AGP) - 2023-03-19 01:07
Mar 19, 2023
dd3db90
CI (AGP) - 2023-03-26 01:03
Mar 26, 2023
c002ffb
CI (AGP) - 2023-04-02 01:01
Apr 2, 2023
92403bb
CI (AGP) - 2023-04-09 00:57
Apr 9, 2023
cb01555
CI (AGP) - 2023-04-16 00:59
Apr 16, 2023
9f1b920
CI (AGP) - 2023-04-23 01:02
Apr 23, 2023
4d0b82d
CI (AGP) - 2023-04-30 01:03
Apr 30, 2023
206ebbf
CI (AGP) - 2023-05-07 01:01
May 7, 2023
30feb6e
CI (AGP) - 2023-05-14 01:00
May 14, 2023
4e70264
CI (AGP) - 2023-05-21 01:01
May 21, 2023
2f76cf5
CI (AGP) - 2023-05-28 01:04
May 28, 2023
c688438
CI (AGP) - 2023-06-04 01:15
Jun 4, 2023
bc04893
CI (AGP) - 2023-06-11 01:13
Jun 11, 2023
e3dc4a2
CI (AGP) - 2023-06-18 01:12
Jun 18, 2023
de64107
CI (AGP) - 2023-06-25 01:18
Jun 25, 2023
71856a1
CI (AGP) - 2023-07-02 01:15
Jul 2, 2023
c2e2e75
CI (AGP) - 2023-07-09 01:17
Jul 9, 2023
48d2cf2
CI (AGP) - 2023-07-16 01:21
Jul 16, 2023
6cfdb88
CI (AGP) - 2023-07-23 01:07
Jul 23, 2023
875bc25
CI (AGP) - 2023-07-30 01:00
Jul 30, 2023
b65dd1b
CI (AGP) - 2023-08-06 00:53
Aug 6, 2023
2d7651d
CI (AGP) - 2023-08-13 00:50
Aug 13, 2023
7880c66
CI (AGP) - 2023-08-22 04:55
Aug 22, 2023
922bbbe
CI (AGP) - 2023-08-22 04:57
Aug 22, 2023
25ba72e
CI (AGP) - 2023-08-22 05:05
Aug 22, 2023
78304fa
CI (AGP) - 2023-08-22 05:17
Aug 22, 2023
810a348
CI (AGP) - 2023-08-22 05:28
Aug 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/.agp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

Auto Github Push (AGP)
https://github.com/ms-jpq/auto-github-push

---
2023-08-22 05:28
6 changes: 1 addition & 5 deletions src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,11 +301,7 @@ impl TryConvert for Proc {
///
/// This effectivly makes the closure's lifetime managed by Ruby. It will be
/// dropped when the returned `Value` is garbage collected.
fn wrap_closure<F, R>(func: F) -> (*mut F, Value)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this because this needed to be polymorphic over different types of closures

where
F: FnMut(&[Value], Option<Proc>) -> R,
R: BlockReturn,
{
pub(crate) fn wrap_closure<F>(func: F) -> (*mut F, Value) {
struct Closure();
impl DataTypeFunctions for Closure {}
let data_type = memoize!(DataType: {
Expand Down
15 changes: 13 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
//! Rust types for working with Ruby Exceptions and other interrupts.

use std::{any::Any, borrow::Cow, ffi::CString, fmt, mem::transmute, ops::Deref, os::raw::c_int};
use std::{
any::Any, borrow::Cow, ffi::CString, fmt, mem::transmute, ops::Deref, os::raw::c_int, ptr::null,
};

use crate::ruby_sys::{
rb_bug, rb_ensure, rb_errinfo, rb_exc_raise, rb_iter_break, rb_iter_break_value, rb_jump_tag,
rb_protect, rb_raise, rb_set_errinfo, rb_warning, ruby_special_consts, VALUE,
rb_protect, rb_raise, rb_set_errinfo, rb_sys_fail, rb_warning, ruby_special_consts, VALUE,
};

use crate::{
Expand Down Expand Up @@ -92,6 +94,15 @@ impl Error {
};
Self::Error(exception::fatal(), msg)
}

/// Akin to io::Error::last_os_error()
pub(crate) fn last_os_error() -> Self {
protect(|| {
unsafe { rb_sys_fail(null()) };
Value::default()
})
.unwrap_err()
}
}

impl fmt::Display for Error {
Expand Down
32 changes: 24 additions & 8 deletions src/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

use std::{fmt, ops::Deref};

use crate::ruby_sys::{
rb_eArgError, rb_eEOFError, rb_eEncCompatError, rb_eEncodingError, rb_eException, rb_eFatal,
rb_eFloatDomainError, rb_eFrozenError, rb_eIOError, rb_eIndexError, rb_eInterrupt,
rb_eKeyError, rb_eLoadError, rb_eLocalJumpError, rb_eMathDomainError, rb_eNameError,
rb_eNoMemError, rb_eNoMethodError, rb_eNotImpError, rb_eRangeError, rb_eRegexpError,
rb_eRuntimeError, rb_eScriptError, rb_eSecurityError, rb_eSignal, rb_eStandardError,
rb_eStopIteration, rb_eSyntaxError, rb_eSysStackError, rb_eSystemCallError, rb_eSystemExit,
rb_eThreadError, rb_eTypeError, rb_eZeroDivError, VALUE,
use crate::{
r_string::RString,
ruby_sys::{
rb_eArgError, rb_eEOFError, rb_eEncCompatError, rb_eEncodingError, rb_eException,
rb_eFatal, rb_eFloatDomainError, rb_eFrozenError, rb_eIOError, rb_eIndexError,
rb_eInterrupt, rb_eKeyError, rb_eLoadError, rb_eLocalJumpError, rb_eMathDomainError,
rb_eNameError, rb_eNoMemError, rb_eNoMethodError, rb_eNotImpError, rb_eRangeError,
rb_eRegexpError, rb_eRuntimeError, rb_eScriptError, rb_eSecurityError, rb_eSignal,
rb_eStandardError, rb_eStopIteration, rb_eSyntaxError, rb_eSysStackError,
rb_eSystemCallError, rb_eSystemExit, rb_eThreadError, rb_eTypeError, rb_eZeroDivError,
rb_syserr_new_str, VALUE,
},
};

#[cfg(ruby_gte_2_7)]
Expand Down Expand Up @@ -250,6 +254,18 @@ impl TryConvert for ExceptionClass {
}
}

impl Exception {
/// Construct Exception from os Error, such as that of
/// `io::Error::last_os_error`
pub fn from_os_error<S>(errno: i32, msg: S) -> Self
where
S: Into<RString>,
{
let msg = msg.into();
unsafe { Self::from_rb_value_unchecked(rb_syserr_new_str(errno, msg.as_rb_value())) }
}
}

/// Return Ruby's `ArgumentError` class.
#[inline]
pub fn arg_error() -> ExceptionClass {
Expand Down
139 changes: 139 additions & 0 deletions src/gvl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
//!

use {
crate::{
error::Error,
ruby_sys::{rb_thread_call_with_gvl, rb_thread_call_without_gvl},
},
std::{
any::Any,
marker::PhantomData,
os::raw::c_void,
panic::{catch_unwind, AssertUnwindSafe},
ptr::null_mut,
},
};

struct ExecutionContext<F, R> {
closure: *mut F,
rval: Option<R>,
}

/// Rust's panic type
pub type Panic = Box<dyn 'static + Send + Any>;

/// A `!Send` guard for invoking thread local GVL operations
pub struct GVLContext(PhantomData<*const ()>);

impl GVLContext {
fn new() -> Self {
Self(PhantomData)
}
}

impl GVLContext {
/// Reacquire GVL for the duration of funtion
pub fn with_gvl<F, R>(&mut self, f: F) -> Result<R, Error>
where
F: FnOnce() -> R,
{
unsafe extern "C" fn call<F, R>(context: *mut c_void) -> *mut c_void
where
F: FnOnce() -> R,
{
let ctx = context as *mut ExecutionContext<F, Result<R, Error>>;
let closure = Box::from_raw((*ctx).closure);
let r = catch_unwind(AssertUnwindSafe(closure)).map_err(Error::from_panic);
let prev = (*ctx).rval.replace(r);
debug_assert!(prev.is_none());
null_mut()
}

let handle = Box::into_raw(Box::new(ExecutionContext {
closure: Box::into_raw(Box::new(f)),
rval: None::<Result<R, Error>>,
}));
let call_func = call::<F, R> as unsafe extern "C" fn(*mut c_void) -> *mut c_void;

unsafe {
rb_thread_call_with_gvl(Some(call_func), handle as *mut _);
Box::from_raw(handle)
.rval
.expect("rb_thread_call_without_gvl should have finished execution")
}
}
}

/// Release GVL for the duration of the closure
/// See `RThread::from_fn`'s example.
///
/// Optional `cancel` fn will execute on various thread interrupts.
/// Including signals.
///
/// Pass in `None::<fn()>` if not required.
pub fn without_gvl<F, C, FR, CR>(
f: F,
cancel: Option<C>,
) -> (Result<FR, Error>, Option<Result<CR, Error>>)
where
F: FnOnce(GVLContext) -> FR,
C: FnOnce() -> CR,
{
unsafe extern "C" fn call<F, R>(context: *mut c_void) -> *mut c_void
where
F: FnOnce(GVLContext) -> R,
{
let ctx = context as *mut ExecutionContext<F, Result<R, Panic>>;
let closure = Box::from_raw((*ctx).closure);
let r = catch_unwind(AssertUnwindSafe(|| (closure)(GVLContext::new())));
let prev = (*ctx).rval.replace(r);
debug_assert!(prev.is_none());
null_mut()
}

unsafe extern "C" fn recall<F, R>(context: *mut c_void)
where
F: FnOnce() -> R,
{
let ctx = context as *mut ExecutionContext<F, Result<R, Panic>>;
let closure = Box::from_raw((*ctx).closure);
let r = catch_unwind(AssertUnwindSafe(closure));
let prev = (*ctx).rval.replace(r);
debug_assert!(prev.is_none());
}

let call_handle = Box::into_raw(Box::new(ExecutionContext {
closure: Box::into_raw(Box::new(f)),
rval: None::<Result<FR, Panic>>,
}));
let recall_handle = cancel.map(|c| {
Box::into_raw(Box::new(ExecutionContext {
closure: Box::into_raw(Box::new(c)),
rval: None::<Result<CR, Panic>>,
}))
});

let call_func = call::<F, FR> as unsafe extern "C" fn(*mut c_void) -> *mut c_void;
let recall_func = recall_handle.map(|_| recall::<C, CR> as unsafe extern "C" fn(*mut c_void));

unsafe {
rb_thread_call_without_gvl(
Some(call_func),
call_handle as *mut _,
recall_func,
match recall_handle {
Some(handle) => handle as *mut _,
None => null_mut(),
},
);

let lhs = Box::from_raw(call_handle)
.rval
.expect("rb_thread_call_without_gvl should have finished execution")
.map_err(Error::from_panic);
let rhs = recall_handle
.and_then(|handle| Box::from_raw(handle).rval)
.map(|rval| rval.map_err(Error::from_panic));
(lhs, rhs)
}
}
Loading