ratomic 0.1.0 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 997065e8a812fe84d836e06402ba1250d54116a251aa220cc255799f41c1da57
4
- data.tar.gz: c0b6ea1afbf4d04b4638150a63063ad63e54d52aa0ee4ef4a6816d3240ec74a1
3
+ metadata.gz: b4ca3b68838c5f869284756b01f00e56960cbb5dff8e640efc03682d10d28a50
4
+ data.tar.gz: 959794b19074d1ecfba5bdb08223ba372a6443fbc96fe833d0ce324aa3c52d5e
5
5
  SHA512:
6
- metadata.gz: a085aa02d2ff513781b1ef44d89505f9bc397c254840126d3d8a2560b6c293257ff43b49c0c96450c915c1494d440e6272b6efb704a2477a0d1a60fd1ca6cd55
7
- data.tar.gz: 92439604f4f93a306d6b672db005f1864d1afad8c9c5cd8b7e64dfb045c941ea576e6b45802647d5c32618db1e461715a8e27f7246028acfa5438c621624b331
6
+ metadata.gz: 9697f964c65bdc3a951da84836ebadf947d370d74efd258015fb5401267acd6d78248de238f9da6db60edecccbe0a8bbd83a327e424d6fb6e74066ee60fe16de
7
+ data.tar.gz: 8bbbba4064050e577b23b48e8363653b5438ea157a68cffc607a53588e2785fdc9c2d5879d846593fa9f2757667df1df77784811c239b4f5b5d9cc684f00ae74
data/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.2.1] - 2026-06-04
4
+
5
+ - Fix `Ratomic::Queue` slot indexing for non-power-of-two capacities.
6
+ - Fix `Ratomic::Map#fetch_and_modify` to propagate block exceptions instead of panicking.
7
+
8
+ ## [0.2.0] - 2026-06-04
9
+
10
+ - Drop Ruby 3.x support and require Ruby 4.
11
+ - Add `length`, `size`, `peek`, and `empty?` methods to `Ratomic::Queue`.
12
+ - Change `Ratomic::Pool` to use Ruby 4 `Ractor::Port` ownership transfer semantics, fixing the unsafe stale-reference behavior reported in [#5]
13
+ (https://github.com/mperham/ratomic/issues/5).
14
+ - Organize Ruby wrapper code by primitive.
15
+ - Add primitive contract tests for `Counter`, `Map`, `Queue`, and `Pool`.
16
+ - Add SimpleCov coverage reporting.
17
+ - Undefine native typed-data default allocators to remove Ruby 4 warnings.
18
+
19
+ ## [0.1.0] - 2025-03-20
20
+
21
+ - Initial release
data/Cargo.lock ADDED
@@ -0,0 +1,381 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "aho-corasick"
7
+ version = "1.1.4"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
10
+ dependencies = [
11
+ "memchr",
12
+ ]
13
+
14
+ [[package]]
15
+ name = "bindgen"
16
+ version = "0.72.1"
17
+ source = "registry+https://github.com/rust-lang/crates.io-index"
18
+ checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
19
+ dependencies = [
20
+ "bitflags",
21
+ "cexpr",
22
+ "clang-sys",
23
+ "itertools",
24
+ "proc-macro2",
25
+ "quote",
26
+ "regex",
27
+ "rustc-hash",
28
+ "shlex",
29
+ "syn",
30
+ ]
31
+
32
+ [[package]]
33
+ name = "bitflags"
34
+ version = "2.12.1"
35
+ source = "registry+https://github.com/rust-lang/crates.io-index"
36
+ checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a"
37
+
38
+ [[package]]
39
+ name = "cexpr"
40
+ version = "0.6.0"
41
+ source = "registry+https://github.com/rust-lang/crates.io-index"
42
+ checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
43
+ dependencies = [
44
+ "nom",
45
+ ]
46
+
47
+ [[package]]
48
+ name = "cfg-if"
49
+ version = "1.0.4"
50
+ source = "registry+https://github.com/rust-lang/crates.io-index"
51
+ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
52
+
53
+ [[package]]
54
+ name = "clang-sys"
55
+ version = "1.8.1"
56
+ source = "registry+https://github.com/rust-lang/crates.io-index"
57
+ checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
58
+ dependencies = [
59
+ "glob",
60
+ "libc",
61
+ "libloading",
62
+ ]
63
+
64
+ [[package]]
65
+ name = "crossbeam-channel"
66
+ version = "0.5.15"
67
+ source = "registry+https://github.com/rust-lang/crates.io-index"
68
+ checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
69
+ dependencies = [
70
+ "crossbeam-utils",
71
+ ]
72
+
73
+ [[package]]
74
+ name = "crossbeam-utils"
75
+ version = "0.8.21"
76
+ source = "registry+https://github.com/rust-lang/crates.io-index"
77
+ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
78
+
79
+ [[package]]
80
+ name = "dashmap"
81
+ version = "6.2.1"
82
+ source = "registry+https://github.com/rust-lang/crates.io-index"
83
+ checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c"
84
+ dependencies = [
85
+ "cfg-if",
86
+ "crossbeam-utils",
87
+ "hashbrown",
88
+ "lock_api",
89
+ "once_cell",
90
+ "parking_lot_core",
91
+ ]
92
+
93
+ [[package]]
94
+ name = "either"
95
+ version = "1.16.0"
96
+ source = "registry+https://github.com/rust-lang/crates.io-index"
97
+ checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
98
+
99
+ [[package]]
100
+ name = "glob"
101
+ version = "0.3.3"
102
+ source = "registry+https://github.com/rust-lang/crates.io-index"
103
+ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
104
+
105
+ [[package]]
106
+ name = "hashbrown"
107
+ version = "0.14.5"
108
+ source = "registry+https://github.com/rust-lang/crates.io-index"
109
+ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
110
+
111
+ [[package]]
112
+ name = "itertools"
113
+ version = "0.13.0"
114
+ source = "registry+https://github.com/rust-lang/crates.io-index"
115
+ checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
116
+ dependencies = [
117
+ "either",
118
+ ]
119
+
120
+ [[package]]
121
+ name = "lazy_static"
122
+ version = "1.5.0"
123
+ source = "registry+https://github.com/rust-lang/crates.io-index"
124
+ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
125
+
126
+ [[package]]
127
+ name = "libc"
128
+ version = "0.2.186"
129
+ source = "registry+https://github.com/rust-lang/crates.io-index"
130
+ checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
131
+
132
+ [[package]]
133
+ name = "libloading"
134
+ version = "0.8.9"
135
+ source = "registry+https://github.com/rust-lang/crates.io-index"
136
+ checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
137
+ dependencies = [
138
+ "cfg-if",
139
+ "windows-link",
140
+ ]
141
+
142
+ [[package]]
143
+ name = "lock_api"
144
+ version = "0.4.14"
145
+ source = "registry+https://github.com/rust-lang/crates.io-index"
146
+ checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
147
+ dependencies = [
148
+ "scopeguard",
149
+ ]
150
+
151
+ [[package]]
152
+ name = "magnus"
153
+ version = "0.8.2"
154
+ source = "registry+https://github.com/rust-lang/crates.io-index"
155
+ checksum = "3b36a5b126bbe97eb0d02d07acfeb327036c6319fd816139a49824a83b7f9012"
156
+ dependencies = [
157
+ "magnus-macros",
158
+ "rb-sys",
159
+ "rb-sys-env",
160
+ "seq-macro",
161
+ ]
162
+
163
+ [[package]]
164
+ name = "magnus-macros"
165
+ version = "0.8.0"
166
+ source = "registry+https://github.com/rust-lang/crates.io-index"
167
+ checksum = "47607461fd8e1513cb4f2076c197d8092d921a1ea75bd08af97398f593751892"
168
+ dependencies = [
169
+ "proc-macro2",
170
+ "quote",
171
+ "syn",
172
+ ]
173
+
174
+ [[package]]
175
+ name = "memchr"
176
+ version = "2.8.1"
177
+ source = "registry+https://github.com/rust-lang/crates.io-index"
178
+ checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
179
+
180
+ [[package]]
181
+ name = "minimal-lexical"
182
+ version = "0.2.1"
183
+ source = "registry+https://github.com/rust-lang/crates.io-index"
184
+ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
185
+
186
+ [[package]]
187
+ name = "nom"
188
+ version = "7.1.3"
189
+ source = "registry+https://github.com/rust-lang/crates.io-index"
190
+ checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
191
+ dependencies = [
192
+ "memchr",
193
+ "minimal-lexical",
194
+ ]
195
+
196
+ [[package]]
197
+ name = "once_cell"
198
+ version = "1.21.4"
199
+ source = "registry+https://github.com/rust-lang/crates.io-index"
200
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
201
+
202
+ [[package]]
203
+ name = "parking_lot"
204
+ version = "0.12.5"
205
+ source = "registry+https://github.com/rust-lang/crates.io-index"
206
+ checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
207
+ dependencies = [
208
+ "lock_api",
209
+ "parking_lot_core",
210
+ ]
211
+
212
+ [[package]]
213
+ name = "parking_lot_core"
214
+ version = "0.9.12"
215
+ source = "registry+https://github.com/rust-lang/crates.io-index"
216
+ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
217
+ dependencies = [
218
+ "cfg-if",
219
+ "libc",
220
+ "redox_syscall",
221
+ "smallvec",
222
+ "windows-link",
223
+ ]
224
+
225
+ [[package]]
226
+ name = "proc-macro2"
227
+ version = "1.0.106"
228
+ source = "registry+https://github.com/rust-lang/crates.io-index"
229
+ checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
230
+ dependencies = [
231
+ "unicode-ident",
232
+ ]
233
+
234
+ [[package]]
235
+ name = "quote"
236
+ version = "1.0.45"
237
+ source = "registry+https://github.com/rust-lang/crates.io-index"
238
+ checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
239
+ dependencies = [
240
+ "proc-macro2",
241
+ ]
242
+
243
+ [[package]]
244
+ name = "ratomic"
245
+ version = "0.1.0"
246
+ dependencies = [
247
+ "crossbeam-channel",
248
+ "dashmap",
249
+ "libc",
250
+ "magnus",
251
+ "parking_lot",
252
+ "rb-sys",
253
+ "rb-sys-env",
254
+ ]
255
+
256
+ [[package]]
257
+ name = "rb-sys"
258
+ version = "0.9.128"
259
+ source = "registry+https://github.com/rust-lang/crates.io-index"
260
+ checksum = "45ca28513560e56cfb79a62b1fce363c73af170a182024ce880c77ee9429920a"
261
+ dependencies = [
262
+ "rb-sys-build",
263
+ ]
264
+
265
+ [[package]]
266
+ name = "rb-sys-build"
267
+ version = "0.9.128"
268
+ source = "registry+https://github.com/rust-lang/crates.io-index"
269
+ checksum = "ce04b2c55eff3a21aaa623fcc655d94373238e72cac6b3e1a3641ff31649f99a"
270
+ dependencies = [
271
+ "bindgen",
272
+ "lazy_static",
273
+ "proc-macro2",
274
+ "quote",
275
+ "regex",
276
+ "shell-words",
277
+ "syn",
278
+ ]
279
+
280
+ [[package]]
281
+ name = "rb-sys-env"
282
+ version = "0.2.3"
283
+ source = "registry+https://github.com/rust-lang/crates.io-index"
284
+ checksum = "cca7ad6a7e21e72151d56fe2495a259b5670e204c3adac41ee7ef676ea08117a"
285
+
286
+ [[package]]
287
+ name = "redox_syscall"
288
+ version = "0.5.18"
289
+ source = "registry+https://github.com/rust-lang/crates.io-index"
290
+ checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
291
+ dependencies = [
292
+ "bitflags",
293
+ ]
294
+
295
+ [[package]]
296
+ name = "regex"
297
+ version = "1.12.3"
298
+ source = "registry+https://github.com/rust-lang/crates.io-index"
299
+ checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
300
+ dependencies = [
301
+ "aho-corasick",
302
+ "memchr",
303
+ "regex-automata",
304
+ "regex-syntax",
305
+ ]
306
+
307
+ [[package]]
308
+ name = "regex-automata"
309
+ version = "0.4.14"
310
+ source = "registry+https://github.com/rust-lang/crates.io-index"
311
+ checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
312
+ dependencies = [
313
+ "aho-corasick",
314
+ "memchr",
315
+ "regex-syntax",
316
+ ]
317
+
318
+ [[package]]
319
+ name = "regex-syntax"
320
+ version = "0.8.10"
321
+ source = "registry+https://github.com/rust-lang/crates.io-index"
322
+ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
323
+
324
+ [[package]]
325
+ name = "rustc-hash"
326
+ version = "2.1.2"
327
+ source = "registry+https://github.com/rust-lang/crates.io-index"
328
+ checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
329
+
330
+ [[package]]
331
+ name = "scopeguard"
332
+ version = "1.2.0"
333
+ source = "registry+https://github.com/rust-lang/crates.io-index"
334
+ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
335
+
336
+ [[package]]
337
+ name = "seq-macro"
338
+ version = "0.3.6"
339
+ source = "registry+https://github.com/rust-lang/crates.io-index"
340
+ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
341
+
342
+ [[package]]
343
+ name = "shell-words"
344
+ version = "1.1.1"
345
+ source = "registry+https://github.com/rust-lang/crates.io-index"
346
+ checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77"
347
+
348
+ [[package]]
349
+ name = "shlex"
350
+ version = "1.3.0"
351
+ source = "registry+https://github.com/rust-lang/crates.io-index"
352
+ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
353
+
354
+ [[package]]
355
+ name = "smallvec"
356
+ version = "1.15.1"
357
+ source = "registry+https://github.com/rust-lang/crates.io-index"
358
+ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
359
+
360
+ [[package]]
361
+ name = "syn"
362
+ version = "2.0.117"
363
+ source = "registry+https://github.com/rust-lang/crates.io-index"
364
+ checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
365
+ dependencies = [
366
+ "proc-macro2",
367
+ "quote",
368
+ "unicode-ident",
369
+ ]
370
+
371
+ [[package]]
372
+ name = "unicode-ident"
373
+ version = "1.0.24"
374
+ source = "registry+https://github.com/rust-lang/crates.io-index"
375
+ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
376
+
377
+ [[package]]
378
+ name = "windows-link"
379
+ version = "0.2.1"
380
+ source = "registry+https://github.com/rust-lang/crates.io-index"
381
+ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
data/Cargo.toml ADDED
@@ -0,0 +1,8 @@
1
+ [workspace]
2
+ members = ["ext/ratomic"]
3
+ resolver = "2"
4
+
5
+ [profile.release]
6
+ panic = "abort"
7
+ lto = true
8
+ codegen-units = 1
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) Ilya Bylich
4
+ Copyright (c) Contributed Systems LLC
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,181 @@
1
+ # Ratomic
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/ratomic.svg)](https://badge.fury.io/rb/ratomic)
4
+ [![CI](https://github.com/mperham/ratomic/workflows/CI/badge.svg)](https://github.com/mperham/ratomic/actions)
5
+ [![Coverage Status](https://codecov.io/gh/mperham/ratomic/branch/main/graph/badge.svg)](https://codecov.io/gh/mperham/ratomic)
6
+ [![Ruby Version](https://img.shields.io/badge/ruby-%3E%3D%204.0-ruby.svg)](https://www.ruby-lang.org/en/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+
10
+ Ratomic provides mutable data structures for use with Ruby's Ractors.
11
+ This allows Ruby code to scale beyond the infamous GVL.
12
+
13
+ # HELP WANTED!
14
+
15
+ > If you know Rust and Ruby C-extensions, we need your help!
16
+ > This project is brand new and could use your knowledge!
17
+ > If you don't know Rust or C, consider this a challenge to learn and solve.
18
+ > Read through the [issues](//github.com/mperham/ratomic/issues) to find work that sounds interesting to you.
19
+
20
+ ## How to contribute
21
+
22
+ Please make sure to understand our [Code of Conduct](./CODE_OF_CONDUCT.md).
23
+
24
+ After changing code, you can give it a spin with:
25
+
26
+ ```bash
27
+ rake
28
+ ```
29
+
30
+ This should compile the Rust code and run all tests.
31
+ The test suite writes a SimpleCov report to `coverage/index.html` so you can see which Ruby wrapper paths are covered.
32
+
33
+ ## Installation
34
+
35
+ Install the gem and add to the application's Gemfile by executing:
36
+
37
+ ```bash
38
+ bundle add ratomic
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ Ratomic provides several useful Ractor-safe structures.
44
+ Note the APIs available are frequently very limited compared to Ruby's broad API.
45
+
46
+ These structures are designed for use as class-level constants so they can be shared by numerous Ractors.
47
+
48
+ Ratomic has two different safety models:
49
+
50
+ * `Counter`, `Map`, and `Queue` are shared concurrent structures.
51
+ * `Pool` transfers ownership of mutable objects between Ractors.
52
+
53
+ That distinction matters. A mutable pooled object is not shared by multiple Ractors at the same time. It is moved to the caller on checkout and moved back to the pool on checkin.
54
+
55
+ ### `Ratomic::Counter`
56
+
57
+ ```ruby
58
+ c = Ratomic::Counter.new
59
+ c.read # => 0
60
+ c.inc
61
+ c.inc(5)
62
+ c.dec(1)
63
+ c.dec
64
+ c.read # => 4
65
+ c.to_i # => 4
66
+ c.zero? # => false
67
+ ```
68
+
69
+ ### `Ratomic::Pool`
70
+
71
+ A Ractor-safe object pool:
72
+
73
+ ```ruby
74
+ POOL = Ratomic::Pool.new(5, 1.0) { [] }
75
+ POOL.with do |obj|
76
+ # do something with obj
77
+ obj << "work"
78
+ end
79
+ ```
80
+
81
+ `Pool` is an ownership-transfer pool for mutable Ruby objects. It uses Ruby 4's `Ractor::Port` and `move: true` semantics so only one Ractor owns a checked-out object at a time.
82
+
83
+ This design addresses [issue #5](https://github.com/mperham/ratomic/issues/5), where using a pooled object after `with` could lead to memory corruption or a process crash. The fix is Rust-inspired ownership transfer, not Rust's full borrow checker: Ruby enforces the boundary dynamically at runtime through Ractor move semantics, while Rust enforces ownership and borrowing statically at compile time.
84
+
85
+ In that model:
86
+
87
+ * the Rust owner maps to the Ractor that currently checked out the pooled object
88
+ * the Rust move maps to `Ractor::Port#send(..., move: true)`
89
+ * Rust's "cannot use after move" rule maps to Ruby raising `Ractor::MovedError`
90
+ * borrowing is not modeled; `Pool` transfers ownership instead of lending references
91
+
92
+ When an object is checked out:
93
+
94
+ * the pool moves the object to the caller
95
+ * the caller can mutate the object while it owns it
96
+ * the pool cannot hand that object to another Ractor until it is checked in
97
+
98
+ When an object is checked in:
99
+
100
+ * ownership moves back to the pool
101
+ * stale references held by the caller become moved objects
102
+ * using those stale references raises `Ractor::MovedError`
103
+
104
+ This means incorrect usage fails at the Ruby object-ownership boundary rather than allowing two Ractors to mutate the same object concurrently.
105
+
106
+ ```ruby
107
+ outside = nil
108
+
109
+ POOL.with do |obj|
110
+ outside = obj
111
+ obj << "inside"
112
+ end
113
+
114
+ outside << "outside"
115
+ # raises Ractor::MovedError
116
+ ```
117
+
118
+ The lower-level `Ratomic::FixedSizeObjectPool` native class may still exist, but `Ratomic::Pool` does not inherit from it. The public `Pool` API is implemented in Ruby so it can use Ruby's Ractor ownership primitives directly.
119
+
120
+ Manual checkout/checkin is also supported:
121
+
122
+ ```ruby
123
+ obj = POOL.checkout
124
+ raise "pool checkout timeout" if obj.nil?
125
+
126
+ begin
127
+ obj << "manual work"
128
+ ensure
129
+ POOL.checkin(obj) if obj
130
+ end
131
+ ```
132
+
133
+ `checkout` returns `nil` if no pooled object becomes available before the configured timeout. `with` raises `Ratomic::Error` in that case.
134
+
135
+ ### `Ratomic::Map`
136
+
137
+ A Ractor-safe map/hash structure:
138
+
139
+ ```ruby
140
+ HASH = Ratomic::Map.new
141
+ HASH["mike"] = 123
142
+ HASH["mike"] # => 123
143
+ HASH.fetch_and_modify("mike") { |value| value + 1 }
144
+ HASH.length
145
+ HASH.empty?
146
+ HASH.clear
147
+ ```
148
+
149
+ ### `Ratomic::Queue`
150
+
151
+ A multi-producer, multi-consumer queue.
152
+
153
+ ```ruby
154
+ q = Ratomic::Queue.new(128)
155
+
156
+ q.push("hello")
157
+ q << "world"
158
+
159
+ q.size # => 2
160
+ q.empty? # => false
161
+ q.peek # => "hello"
162
+ item = q.pop # => "hello"
163
+ item = q.pop # => "world"
164
+ q.empty? # => true
165
+ ```
166
+ The `.new(capacity)` method initializes the queue with a fixed-size buffer. The capacity must be greater than or equal to 1 and less than or equal to 2<sup>20</sup>.
167
+
168
+ Values that are not a power of two are rounded up to the nearest greater power of two, which enables efficient indexing and wrap-around calculations in the underlying buffer.
169
+
170
+ Since `Ratomic::Queue` is a concurrent queue, the `size`, `empty?`, and `peek` methods provide only a best-effort guess — the values they return might be stale or incorrect.
171
+
172
+ ## Thanks
173
+
174
+ [Ilya Bylich](https://github.com/iliabylich) wrote and documented his original research at [Ruby, Ractors, and Lock-free Data Structures/](https://iliabylich.github.io/ruby-ractors-and-lock-free-data-structures/).
175
+ Thank you for your impressive work, Ilya!
176
+
177
+ This repo is further research into the usability and limitations of Ractor-friendly structures in Ruby code and gems.
178
+
179
+ ## License
180
+
181
+ [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,22 @@
1
+ [package]
2
+ name = "ratomic"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ publish = false
6
+
7
+ [lib]
8
+ crate-type = ["cdylib"]
9
+
10
+ [features]
11
+ simulation = []
12
+
13
+ [dependencies]
14
+ crossbeam-channel = "0.5.14"
15
+ dashmap = "6.1.0"
16
+ libc = "0.2.170"
17
+ magnus = "0.8.2"
18
+ parking_lot = "0.12.3"
19
+ rb-sys = { version = "0.9.128", features = ["stable-api-compiled-fallback"] }
20
+
21
+ [build-dependencies]
22
+ rb-sys-env = "0.2.2"
@@ -0,0 +1,3 @@
1
+ fn main() {
2
+ rb_sys_env::activate().expect("rb-sys environment activation failed");
3
+ }
@@ -1,16 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "mkmf"
4
+ require "rb_sys/mkmf"
4
5
 
5
- # Makes all symbols private by default to avoid unintended conflict
6
- # with other gems. To explicitly export symbols you can use RUBY_FUNC_EXPORTED
7
- # selectively, or entirely remove this flag.
8
- append_cflags("-fvisibility=hidden")
9
-
10
- rust_atomics_path = File.expand_path("../../../rs", __FILE__)
11
- # rubocop:disable Style/GlobalVars
12
- $INCFLAGS << " -I#{rust_atomics_path}"
13
- $LDFLAGS << " -L#{rust_atomics_path}/target/release -lrust_atomics"
14
- # rubocop:enable Style/GlobalVars
15
-
16
- create_makefile("ratomic/ratomic")
6
+ create_rust_makefile("ratomic/ratomic")