ratomic 0.4.1 → 0.4.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/ext/ratomic/src/hashmap.rs +25 -3
- data/ext/ratomic/src/lib.rs +26 -5
- data/lib/ratomic/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 764ab083a8815f4f2bd0958be83d5209b10b21d8765dc19720fedd6d042eec89
|
|
4
|
+
data.tar.gz: 5bf02090ace17e0ca172bcc9f9f2a56f79030f0a92ecf669adecba72aa2ec641
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c7a3e86bfe551b27b28af6655bd7853c1be683d69e759d6b628388282e7443030fe8b56c7e036e1c25f8234de74052fc621747eb94484e84e979b771aaf7ebcc
|
|
7
|
+
data.tar.gz: 03e9c06d8c5771ab340e1219113b5f67c05da3e97c5ad2a5b7ddefb9e5b54103988eb6cb7c299e09a0808e27fec660b3eaea8a7a3fc200a5aa8dd84161faf484
|
data/CHANGELOG.md
CHANGED
data/ext/ratomic/src/hashmap.rs
CHANGED
|
@@ -54,6 +54,21 @@ impl MapStore {
|
|
|
54
54
|
self.map.len()
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
fn with_entry<F, R, W>(&self, key: VALUE, mut on_locked: W, f: F) -> R
|
|
58
|
+
where
|
|
59
|
+
F: FnOnce(Entry<'_, RubyHashEql, VALUE>) -> R,
|
|
60
|
+
W: FnMut(),
|
|
61
|
+
{
|
|
62
|
+
let mut f = Some(f);
|
|
63
|
+
loop {
|
|
64
|
+
if let Some(entry) = self.map.try_entry(RubyHashEql(key)) {
|
|
65
|
+
return f.take().expect("entry closure already used")(entry);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
on_locked();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
57
72
|
pub fn fetch_and_modify<F>(&self, key: VALUE, f: F)
|
|
58
73
|
where
|
|
59
74
|
F: FnOnce(VALUE) -> VALUE,
|
|
@@ -61,11 +76,18 @@ impl MapStore {
|
|
|
61
76
|
self.map.alter(&RubyHashEql(key), |_, value| f(value));
|
|
62
77
|
}
|
|
63
78
|
|
|
64
|
-
pub fn compute<F, E
|
|
79
|
+
pub fn compute<F, E, W>(
|
|
80
|
+
&self,
|
|
81
|
+
key: VALUE,
|
|
82
|
+
missing: VALUE,
|
|
83
|
+
on_locked: W,
|
|
84
|
+
f: F,
|
|
85
|
+
) -> Result<VALUE, E>
|
|
65
86
|
where
|
|
66
87
|
F: FnOnce(VALUE) -> Result<VALUE, E>,
|
|
88
|
+
W: FnMut(),
|
|
67
89
|
{
|
|
68
|
-
|
|
90
|
+
self.with_entry(key, on_locked, |entry| match entry {
|
|
69
91
|
Entry::Occupied(mut entry) => {
|
|
70
92
|
let new_value = f(*entry.get())?;
|
|
71
93
|
entry.insert(new_value);
|
|
@@ -76,7 +98,7 @@ impl MapStore {
|
|
|
76
98
|
entry.insert(new_value);
|
|
77
99
|
Ok(new_value)
|
|
78
100
|
}
|
|
79
|
-
}
|
|
101
|
+
})
|
|
80
102
|
}
|
|
81
103
|
|
|
82
104
|
pub fn update<F, E>(&self, key: VALUE, f: F) -> Result<VALUE, E>
|
data/ext/ratomic/src/lib.rs
CHANGED
|
@@ -18,7 +18,7 @@ use magnus::{
|
|
|
18
18
|
use mpmc_queue::MpmcQueue;
|
|
19
19
|
use parking_lot::Mutex;
|
|
20
20
|
use rb_sys::{rb_ext_ractor_safe, rb_thread_call_without_gvl, ruby_special_consts, VALUE};
|
|
21
|
-
use std::{ffi::c_void, mem::transmute};
|
|
21
|
+
use std::{ffi::c_void, mem::transmute, time::Duration};
|
|
22
22
|
|
|
23
23
|
fn value_to_raw(value: Value) -> VALUE {
|
|
24
24
|
unsafe { transmute::<Value, VALUE>(value) }
|
|
@@ -38,6 +38,22 @@ fn make_shareable(ruby: &Ruby, value: Value) -> Result<Value, Error> {
|
|
|
38
38
|
ractor.funcall("make_shareable", (value,))
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
unsafe extern "C" fn sleep_briefly_without_gvl(_: *mut c_void) -> *mut c_void {
|
|
42
|
+
std::thread::sleep(Duration::from_millis(1));
|
|
43
|
+
std::ptr::null_mut()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fn wait_for_entry_without_gvl() {
|
|
47
|
+
unsafe {
|
|
48
|
+
rb_thread_call_without_gvl(
|
|
49
|
+
Some(sleep_briefly_without_gvl),
|
|
50
|
+
std::ptr::null_mut(),
|
|
51
|
+
None,
|
|
52
|
+
std::ptr::null_mut(),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
41
57
|
struct Counter(AtomicCounter);
|
|
42
58
|
|
|
43
59
|
impl Counter {
|
|
@@ -158,10 +174,15 @@ impl HashMap {
|
|
|
158
174
|
}
|
|
159
175
|
|
|
160
176
|
let proc = ruby.block_proc()?;
|
|
161
|
-
let raw = rb_self.0.compute(
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
177
|
+
let raw = rb_self.0.compute(
|
|
178
|
+
value_to_raw(key),
|
|
179
|
+
qnil_raw(),
|
|
180
|
+
wait_for_entry_without_gvl,
|
|
181
|
+
|value| {
|
|
182
|
+
proc.call::<_, Value>((unsafe { value_from_raw(value) },))
|
|
183
|
+
.map(value_to_raw)
|
|
184
|
+
},
|
|
185
|
+
)?;
|
|
165
186
|
|
|
166
187
|
Ok(unsafe { value_from_raw(raw) }.into_value_with(ruby))
|
|
167
188
|
}
|
data/lib/ratomic/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ratomic
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mike Perham
|
|
@@ -81,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '0'
|
|
83
83
|
requirements: []
|
|
84
|
-
rubygems_version: 4.0.
|
|
84
|
+
rubygems_version: 4.0.16
|
|
85
85
|
specification_version: 4
|
|
86
86
|
summary: Ractor-safe concurrent data structures for Ruby
|
|
87
87
|
test_files: []
|