uringmachine 0.16 → 0.19

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.
Files changed (267) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +3 -0
  3. data/.gitmodules +4 -0
  4. data/CHANGELOG.md +12 -0
  5. data/TODO.md +13 -4
  6. data/examples/bm_send.rb +86 -0
  7. data/examples/fiber_scheduler_demo.rb +71 -0
  8. data/ext/um/um.c +107 -36
  9. data/ext/um/um.h +7 -2
  10. data/ext/um/um_async_op.c +2 -1
  11. data/ext/um/um_class.c +23 -0
  12. data/ext/um/um_const.c +5 -2
  13. data/ext/um/um_stream.c +8 -8
  14. data/ext/um/um_stream_class.c +1 -1
  15. data/ext/um/um_sync.c +2 -2
  16. data/ext/um/um_utils.c +38 -15
  17. data/lib/uringmachine/fiber_scheduler.rb +104 -0
  18. data/lib/uringmachine/version.rb +1 -1
  19. data/test/test_stream.rb +3 -3
  20. data/test/test_um.rb +129 -0
  21. data/vendor/libressl/.github/scripts/changelog.sh +74 -0
  22. data/vendor/libressl/.github/workflows/android.yml +35 -0
  23. data/vendor/libressl/.github/workflows/cifuzz.yml +33 -0
  24. data/vendor/libressl/.github/workflows/cmake-config.yml +98 -0
  25. data/vendor/libressl/.github/workflows/coverity.yml +69 -0
  26. data/vendor/libressl/.github/workflows/emscripten.yml +71 -0
  27. data/vendor/libressl/.github/workflows/fedora-rawhide.yml +39 -0
  28. data/vendor/libressl/.github/workflows/freebsd.yml +71 -0
  29. data/vendor/libressl/.github/workflows/linux.yml +71 -0
  30. data/vendor/libressl/.github/workflows/macos.yml +37 -0
  31. data/vendor/libressl/.github/workflows/release.yml +81 -0
  32. data/vendor/libressl/.github/workflows/rust-openssl.yml +47 -0
  33. data/vendor/libressl/.github/workflows/solaris.yml +37 -0
  34. data/vendor/libressl/.github/workflows/windows.yml +70 -0
  35. data/vendor/libressl/.gitignore +333 -0
  36. data/vendor/libressl/CMakeLists.txt +581 -0
  37. data/vendor/libressl/COPYING +133 -0
  38. data/vendor/libressl/ChangeLog +3280 -0
  39. data/vendor/libressl/FindLibreSSL.cmake +232 -0
  40. data/vendor/libressl/LibreSSLConfig.cmake.in +36 -0
  41. data/vendor/libressl/Makefile.am +60 -0
  42. data/vendor/libressl/Makefile.am.common +20 -0
  43. data/vendor/libressl/OPENBSD_BRANCH +1 -0
  44. data/vendor/libressl/README.md +238 -0
  45. data/vendor/libressl/README.mingw.md +43 -0
  46. data/vendor/libressl/apps/CMakeLists.txt +18 -0
  47. data/vendor/libressl/apps/Makefile.am +5 -0
  48. data/vendor/libressl/apps/nc/CMakeLists.txt +67 -0
  49. data/vendor/libressl/apps/nc/Makefile.am +64 -0
  50. data/vendor/libressl/apps/nc/compat/accept4.c +17 -0
  51. data/vendor/libressl/apps/nc/compat/readpassphrase.c +205 -0
  52. data/vendor/libressl/apps/nc/compat/socket.c +29 -0
  53. data/vendor/libressl/apps/nc/compat/sys/socket.h +30 -0
  54. data/vendor/libressl/apps/ocspcheck/CMakeLists.txt +44 -0
  55. data/vendor/libressl/apps/ocspcheck/Makefile.am +45 -0
  56. data/vendor/libressl/apps/ocspcheck/compat/.gitignore +0 -0
  57. data/vendor/libressl/apps/openssl/CMakeLists.txt +97 -0
  58. data/vendor/libressl/apps/openssl/Makefile.am +108 -0
  59. data/vendor/libressl/apps/openssl/apps_win.c +138 -0
  60. data/vendor/libressl/apps/openssl/certhash_win.c +13 -0
  61. data/vendor/libressl/apps/openssl/compat/clock_gettime_osx.c +26 -0
  62. data/vendor/libressl/apps/openssl/compat/poll_win.c +329 -0
  63. data/vendor/libressl/appveyor.yml +53 -0
  64. data/vendor/libressl/autogen.sh +15 -0
  65. data/vendor/libressl/check-release.sh +86 -0
  66. data/vendor/libressl/cmake_export_symbol.cmake +71 -0
  67. data/vendor/libressl/cmake_uninstall.cmake.in +36 -0
  68. data/vendor/libressl/config +17 -0
  69. data/vendor/libressl/configure.ac +165 -0
  70. data/vendor/libressl/crypto/CMakeLists.txt +863 -0
  71. data/vendor/libressl/crypto/Makefile.am +962 -0
  72. data/vendor/libressl/crypto/Makefile.am.arc4random +46 -0
  73. data/vendor/libressl/crypto/Makefile.am.elf-mips +14 -0
  74. data/vendor/libressl/crypto/Makefile.am.elf-mips64 +14 -0
  75. data/vendor/libressl/crypto/Makefile.am.elf-x86_64 +35 -0
  76. data/vendor/libressl/crypto/Makefile.am.macosx-x86_64 +35 -0
  77. data/vendor/libressl/crypto/Makefile.am.masm-x86_64 +22 -0
  78. data/vendor/libressl/crypto/Makefile.am.mingw64-x86_64 +23 -0
  79. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_darwin.c +60 -0
  80. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_linux.c +62 -0
  81. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_none.c +26 -0
  82. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_windows.c +36 -0
  83. data/vendor/libressl/crypto/arch/loongarch64/crypto_arch.h +21 -0
  84. data/vendor/libressl/crypto/arch/mips/crypto_arch.h +21 -0
  85. data/vendor/libressl/crypto/bn/arch/loongarch64/bn_arch.h +23 -0
  86. data/vendor/libressl/crypto/bn/arch/mips/bn_arch.h +24 -0
  87. data/vendor/libressl/crypto/compat/.gitignore +31 -0
  88. data/vendor/libressl/crypto/compat/arc4random.h +41 -0
  89. data/vendor/libressl/crypto/compat/b_win.c +55 -0
  90. data/vendor/libressl/crypto/compat/bsd-asprintf.c +96 -0
  91. data/vendor/libressl/crypto/compat/crypto_lock_win.c +56 -0
  92. data/vendor/libressl/crypto/compat/explicit_bzero_win.c +13 -0
  93. data/vendor/libressl/crypto/compat/freezero.c +32 -0
  94. data/vendor/libressl/crypto/compat/getdelim.c +78 -0
  95. data/vendor/libressl/crypto/compat/getline.c +40 -0
  96. data/vendor/libressl/crypto/compat/getopt_long.c +528 -0
  97. data/vendor/libressl/crypto/compat/getpagesize.c +18 -0
  98. data/vendor/libressl/crypto/compat/getprogname_linux.c +23 -0
  99. data/vendor/libressl/crypto/compat/getprogname_unimpl.c +7 -0
  100. data/vendor/libressl/crypto/compat/getprogname_windows.c +13 -0
  101. data/vendor/libressl/crypto/compat/posix_win.c +296 -0
  102. data/vendor/libressl/crypto/compat/syslog_r.c +19 -0
  103. data/vendor/libressl/crypto/compat/ui_openssl_win.c +334 -0
  104. data/vendor/libressl/dist.sh +22 -0
  105. data/vendor/libressl/gen-coverage-report.sh +58 -0
  106. data/vendor/libressl/gen-openbsd-tags.sh +20 -0
  107. data/vendor/libressl/include/CMakeLists.txt +61 -0
  108. data/vendor/libressl/include/Makefile.am +79 -0
  109. data/vendor/libressl/include/arch/loongarch64/opensslconf.h +150 -0
  110. data/vendor/libressl/include/arch/mips/opensslconf.h +150 -0
  111. data/vendor/libressl/include/compat/arpa/inet.h +15 -0
  112. data/vendor/libressl/include/compat/arpa/nameser.h +25 -0
  113. data/vendor/libressl/include/compat/cet.h +19 -0
  114. data/vendor/libressl/include/compat/dirent.h +17 -0
  115. data/vendor/libressl/include/compat/dirent_msvc.h +611 -0
  116. data/vendor/libressl/include/compat/endian.h +161 -0
  117. data/vendor/libressl/include/compat/err.h +95 -0
  118. data/vendor/libressl/include/compat/fcntl.h +32 -0
  119. data/vendor/libressl/include/compat/getopt.h +50 -0
  120. data/vendor/libressl/include/compat/limits.h +25 -0
  121. data/vendor/libressl/include/compat/netdb.h +10 -0
  122. data/vendor/libressl/include/compat/netinet/in.h +19 -0
  123. data/vendor/libressl/include/compat/netinet/ip.h +49 -0
  124. data/vendor/libressl/include/compat/netinet/tcp.h +10 -0
  125. data/vendor/libressl/include/compat/poll.h +63 -0
  126. data/vendor/libressl/include/compat/pthread.h +122 -0
  127. data/vendor/libressl/include/compat/readpassphrase.h +44 -0
  128. data/vendor/libressl/include/compat/resolv.h +24 -0
  129. data/vendor/libressl/include/compat/stdint.h +31 -0
  130. data/vendor/libressl/include/compat/stdio.h +65 -0
  131. data/vendor/libressl/include/compat/stdlib.h +57 -0
  132. data/vendor/libressl/include/compat/string.h +98 -0
  133. data/vendor/libressl/include/compat/sys/_null.h +18 -0
  134. data/vendor/libressl/include/compat/sys/ioctl.h +11 -0
  135. data/vendor/libressl/include/compat/sys/mman.h +19 -0
  136. data/vendor/libressl/include/compat/sys/param.h +15 -0
  137. data/vendor/libressl/include/compat/sys/queue.h +536 -0
  138. data/vendor/libressl/include/compat/sys/select.h +10 -0
  139. data/vendor/libressl/include/compat/sys/socket.h +18 -0
  140. data/vendor/libressl/include/compat/sys/stat.h +129 -0
  141. data/vendor/libressl/include/compat/sys/time.h +37 -0
  142. data/vendor/libressl/include/compat/sys/tree.h +1006 -0
  143. data/vendor/libressl/include/compat/sys/types.h +69 -0
  144. data/vendor/libressl/include/compat/sys/uio.h +17 -0
  145. data/vendor/libressl/include/compat/syslog.h +38 -0
  146. data/vendor/libressl/include/compat/time.h +59 -0
  147. data/vendor/libressl/include/compat/unistd.h +83 -0
  148. data/vendor/libressl/include/compat/win32netcompat.h +57 -0
  149. data/vendor/libressl/include/openssl/Makefile.am.tpl +45 -0
  150. data/vendor/libressl/libcrypto.pc.in +28 -0
  151. data/vendor/libressl/libressl.pub +2 -0
  152. data/vendor/libressl/libssl.pc.in +28 -0
  153. data/vendor/libressl/libtls.pc.in +28 -0
  154. data/vendor/libressl/m4/ax_add_fortify_source.m4 +80 -0
  155. data/vendor/libressl/m4/ax_check_compile_flag.m4 +53 -0
  156. data/vendor/libressl/m4/check-hardening-options.m4 +110 -0
  157. data/vendor/libressl/m4/check-libc.m4 +189 -0
  158. data/vendor/libressl/m4/check-os-options.m4 +181 -0
  159. data/vendor/libressl/m4/disable-compiler-warnings.m4 +44 -0
  160. data/vendor/libressl/man/CMakeLists.txt +26 -0
  161. data/vendor/libressl/man/links +2780 -0
  162. data/vendor/libressl/man/update_links.sh +25 -0
  163. data/vendor/libressl/openssl.pc.in +11 -0
  164. data/vendor/libressl/patches/bn_shift.patch +34 -0
  165. data/vendor/libressl/patches/crypto_arch.h.patch +34 -0
  166. data/vendor/libressl/patches/crypto_namespace.h.patch +22 -0
  167. data/vendor/libressl/patches/netcat.c.patch +178 -0
  168. data/vendor/libressl/patches/openssl.c.patch +12 -0
  169. data/vendor/libressl/patches/opensslfeatures.h.patch +49 -0
  170. data/vendor/libressl/patches/patch-amd64-crypto-cpu-caps.c.patch +20 -0
  171. data/vendor/libressl/patches/patch-i386-crypto-cpu-caps.c.patch +20 -0
  172. data/vendor/libressl/patches/speed.c.patch +114 -0
  173. data/vendor/libressl/patches/ssl_namespace.h.patch +21 -0
  174. data/vendor/libressl/patches/tls.h.patch +16 -0
  175. data/vendor/libressl/patches/tls_config.c.patch +15 -0
  176. data/vendor/libressl/patches/win32_amd64_bn_arch.h.patch +28 -0
  177. data/vendor/libressl/patches/windows_headers.patch +80 -0
  178. data/vendor/libressl/scripts/config.guess +1774 -0
  179. data/vendor/libressl/scripts/config.sub +1907 -0
  180. data/vendor/libressl/scripts/i686-w64-mingw32.cmake +9 -0
  181. data/vendor/libressl/scripts/test +210 -0
  182. data/vendor/libressl/scripts/wrap-compiler-for-flag-check +31 -0
  183. data/vendor/libressl/scripts/x86_64-w64-mingw32.cmake +9 -0
  184. data/vendor/libressl/ssl/CMakeLists.txt +183 -0
  185. data/vendor/libressl/ssl/Makefile.am +187 -0
  186. data/vendor/libressl/tests/CMakeLists.txt +970 -0
  187. data/vendor/libressl/tests/Makefile.am +944 -0
  188. data/vendor/libressl/tests/aeadtest.sh +30 -0
  189. data/vendor/libressl/tests/arc4randomforktest.sh +21 -0
  190. data/vendor/libressl/tests/asn1time_small.test +10 -0
  191. data/vendor/libressl/tests/cmake/CMakeLists.txt +52 -0
  192. data/vendor/libressl/tests/cmake/crypto.c +7 -0
  193. data/vendor/libressl/tests/cmake/ssl.c +6 -0
  194. data/vendor/libressl/tests/cmake/tls.c +6 -0
  195. data/vendor/libressl/tests/compat/pipe2.c +186 -0
  196. data/vendor/libressl/tests/dtlstest.sh +28 -0
  197. data/vendor/libressl/tests/evptest.sh +22 -0
  198. data/vendor/libressl/tests/keypairtest.sh +27 -0
  199. data/vendor/libressl/tests/mlkem_tests.sh +39 -0
  200. data/vendor/libressl/tests/ocsptest.bat +25 -0
  201. data/vendor/libressl/tests/ocsptest.sh +23 -0
  202. data/vendor/libressl/tests/openssl.cnf +29 -0
  203. data/vendor/libressl/tests/optionstest.c +381 -0
  204. data/vendor/libressl/tests/pidwraptest.c +85 -0
  205. data/vendor/libressl/tests/pidwraptest.sh +26 -0
  206. data/vendor/libressl/tests/quictest.bat +27 -0
  207. data/vendor/libressl/tests/quictest.sh +30 -0
  208. data/vendor/libressl/tests/renegotiation_test.bat +27 -0
  209. data/vendor/libressl/tests/renegotiation_test.sh +30 -0
  210. data/vendor/libressl/tests/rfc5280time_small.test +10 -0
  211. data/vendor/libressl/tests/servertest.bat +27 -0
  212. data/vendor/libressl/tests/servertest.sh +30 -0
  213. data/vendor/libressl/tests/shutdowntest.bat +27 -0
  214. data/vendor/libressl/tests/shutdowntest.sh +30 -0
  215. data/vendor/libressl/tests/ssltest.bat +32 -0
  216. data/vendor/libressl/tests/ssltest.sh +48 -0
  217. data/vendor/libressl/tests/testdsa.bat +47 -0
  218. data/vendor/libressl/tests/testdsa.sh +57 -0
  219. data/vendor/libressl/tests/testenc.bat +85 -0
  220. data/vendor/libressl/tests/testenc.sh +93 -0
  221. data/vendor/libressl/tests/testrsa.bat +47 -0
  222. data/vendor/libressl/tests/testrsa.sh +57 -0
  223. data/vendor/libressl/tests/testssl.bat +171 -0
  224. data/vendor/libressl/tests/tlstest.bat +27 -0
  225. data/vendor/libressl/tests/tlstest.sh +28 -0
  226. data/vendor/libressl/tls/CMakeLists.txt +125 -0
  227. data/vendor/libressl/tls/Makefile.am +76 -0
  228. data/vendor/libressl/tls/compat/ftruncate.c +17 -0
  229. data/vendor/libressl/tls/compat/pread.c +29 -0
  230. data/vendor/libressl/tls/compat/pwrite.c +29 -0
  231. data/vendor/libressl/update.sh +460 -0
  232. data/vendor/liburing/.github/workflows/ci.yml +8 -0
  233. data/vendor/liburing/configure +23 -2
  234. data/vendor/liburing/examples/helpers.c +1 -1
  235. data/vendor/liburing/examples/helpers.h +1 -1
  236. data/vendor/liburing/examples/reg-wait.c +3 -3
  237. data/vendor/liburing/examples/zcrx.c +5 -5
  238. data/vendor/liburing/liburing.spec +1 -1
  239. data/vendor/liburing/src/include/liburing/io_uring.h +16 -0
  240. data/vendor/liburing/src/include/liburing.h +20 -4
  241. data/vendor/liburing/src/lib.h +2 -4
  242. data/vendor/liburing/src/liburing-ffi.map +7 -0
  243. data/vendor/liburing/src/liburing.map +7 -0
  244. data/vendor/liburing/src/register.c +5 -0
  245. data/vendor/liburing/src/sanitize.c +5 -4
  246. data/vendor/liburing/src/setup.c +43 -28
  247. data/vendor/liburing/test/Makefile +7 -0
  248. data/vendor/liburing/test/cmd-discard.c +2 -2
  249. data/vendor/liburing/test/evfd-short-read.c +84 -0
  250. data/vendor/liburing/test/fdinfo-sqpoll.c +117 -0
  251. data/vendor/liburing/test/fdinfo.c +1 -1
  252. data/vendor/liburing/test/fixed-buf-merge.c +2 -2
  253. data/vendor/liburing/test/futex-kill.c +135 -0
  254. data/vendor/liburing/test/helpers.c +1 -1
  255. data/vendor/liburing/test/helpers.h +1 -1
  256. data/vendor/liburing/test/init-mem.c +50 -12
  257. data/vendor/liburing/test/io_uring_passthrough.c +25 -6
  258. data/vendor/liburing/test/msg-ring.c +123 -9
  259. data/vendor/liburing/test/recv-bundle-short-ooo.c +16 -1
  260. data/vendor/liburing/test/recv-inc-ooo.c +411 -0
  261. data/vendor/liburing/test/recv-mshot-fair.c +513 -0
  262. data/vendor/liburing/test/reg-wait.c +14 -14
  263. data/vendor/liburing/test/send-zerocopy.c +4 -4
  264. data/vendor/liburing/test/timerfd-short-read.c +81 -0
  265. data/vendor/liburing/test/timestamp.c +382 -0
  266. data/vendor/liburing/test/zcrx.c +22 -22
  267. metadata +224 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31417b87cc8d871a492fccfd525b4f991b7ab69546503797c675bdaa07dfe00d
4
- data.tar.gz: b64826a1efb663adad00c61733c37234ace8637725447d85a7b5819cde652cf8
3
+ metadata.gz: 2e4b4b986a75268a9de9dbafacd7d2a5c31cc08058b86a9681757be698fe697e
4
+ data.tar.gz: 99007eb49069d9cfebc70ce6da9c45cbbd5e7c4d518892869ddcb55c401b1cdb
5
5
  SHA512:
6
- metadata.gz: eb438c42b59e8c601bc1a591e9d750fd475bf416e5e44945c6492a4ef46bf20daf89ed6af002e36a9df7f4f2f9d79689976080262cc479723cd5b963e7de4e4f
7
- data.tar.gz: 69503b7a95f2316e4847b1f65b667c2f023df4a4388c3f15fffad5b16fc6577ab537d579523ec48a69a79f282cefab926a00821e96d63e274edebfa4cc663e57
6
+ metadata.gz: f7c55065ac4aef687f91236bf5cb55be4756dee002e61e627775a93d74d069a8ca45372c43cc71d31efce4b33cfb623443a7ef53b929563b48ec8a0e59cbdf92
7
+ data.tar.gz: 066a85ff0f7218e410abdc89e63cc20ae1ff858ecbc857a84f83ab812286fb1f6dd099d44e254452f466d66569046de3cffe0ba9d7d4f52bb1717670a34c5398
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: noteflakes
data/.gitmodules CHANGED
@@ -1,3 +1,7 @@
1
1
  [submodule "vendor/liburing"]
2
2
  path = vendor/liburing
3
3
  url = https://github.com/axboe/liburing
4
+
5
+ [submodule "vendor/libressl"]
6
+ path = vendor/libressl
7
+ url = https://github.com/libressl/portable
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # 0.19 2025-10-27
2
+
3
+ - Fix usage of `RAISE_IF_EXCEPTION` after `RB_GC_GUARD`
4
+
5
+ # 0.18 2025-08-30
6
+
7
+ - Fix `#write_async` to properly mark the given string
8
+
9
+ # 0.17 2025-07-15
10
+
11
+ - Add `#send_bundle` method
12
+
1
13
  # 2025-07-06 Version 0.16
2
14
 
3
15
  - Load UM version on require
data/TODO.md CHANGED
@@ -1,13 +1,22 @@
1
- # ops
1
+ ## useful concurrency tools
2
+
3
+ - debounce
4
+
5
+ ```ruby
6
+ debouncer = UM.debounce { }
7
+ ```
8
+
9
+ ## ops
2
10
 
3
11
  - [ ] multishot timeout
4
12
  - [v] machine.periodically(interval) { ... }
5
13
  - [ ] machine.prep_timeout_multishot(interval)
6
14
 
15
+ - writev
7
16
  - splice / - tee
8
17
  - sendto
9
18
  - recvfrom
10
- - poll_add / poll_remove / poll_multishot / poll_update
19
+ - poll_multishot
11
20
  - fsync
12
21
  - mkdir / mkdirat
13
22
  - link / linkat / unlink / unlinkat / symlink
@@ -17,12 +26,12 @@
17
26
  - getxattr / setxattr
18
27
  - send_bundle / recv_bundle (kernel >= 6.10)
19
28
 
20
- # actors
29
+ ## actors
21
30
 
22
31
  When doing a `call`, we need to provide a mailbox for the response. can this be
23
32
  automatic?
24
33
 
25
- # streams
34
+ ## streams
26
35
 
27
36
  We're still missing:
28
37
 
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+ gem 'uringmachine', path: '..'
8
+ gem 'benchmark-ips'
9
+ end
10
+
11
+ require 'benchmark/ips'
12
+ require 'uringmachine'
13
+
14
+ @machine = UM.new
15
+
16
+ make_socket_pair = -> do
17
+ port = 10000 + rand(30000)
18
+ server_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
19
+ @machine.setsockopt(server_fd, UM::SOL_SOCKET, UM::SO_REUSEADDR, true)
20
+ @machine.bind(server_fd, '127.0.0.1', port)
21
+ @machine.listen(server_fd, UM::SOMAXCONN)
22
+
23
+ client_conn_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
24
+ @machine.connect(client_conn_fd, '127.0.0.1', port)
25
+
26
+ server_conn_fd = @machine.accept(server_fd)
27
+
28
+ @machine.close(server_fd)
29
+ [client_conn_fd, server_conn_fd]
30
+ end
31
+
32
+ @client_fd, @server_fd = make_socket_pair.()
33
+
34
+ @read_buf = +''
35
+ @read_fiber = @machine.spin do
36
+ while true
37
+ @machine.read(@client_fd, @read_buf, 65536, 0)
38
+ end
39
+ end
40
+
41
+ STR_COUNT = ARGV[0]&.to_i || 3
42
+ STR_SIZE = ARGV[1]&.to_i || 100
43
+
44
+ @parts = ['*' * STR_SIZE] * STR_COUNT
45
+
46
+ @server_io = IO.new(@server_fd)
47
+ @server_io.sync = true
48
+ def io_write
49
+ @server_io.write(*@parts)
50
+ @machine.snooze
51
+ end
52
+
53
+ def um_write
54
+ str = @parts.join
55
+ len = str.bytesize
56
+
57
+ while len > 0
58
+ ret = @machine.write(@server_fd, str, len)
59
+ len -= ret
60
+ str = str[ret..-1] if len > 0
61
+ end
62
+ end
63
+
64
+ def um_send
65
+ str = @parts.join
66
+ @machine.send(@server_fd, str, str.bytesize, UM::MSG_WAITALL)
67
+ end
68
+
69
+ @bgid = @machine.setup_buffer_ring(0, 8)
70
+ def um_send_bundle
71
+ @machine.send_bundle(@server_fd, @bgid, @parts)
72
+ end
73
+
74
+ # um_send_bundle
75
+ # 10.times { @machine.snooze }
76
+ # exit
77
+
78
+ p(STR_COUNT:, STR_SIZE:)
79
+
80
+ Benchmark.ips do |x|
81
+ x.report('IO#write') { io_write }
82
+ x.report('UM#write') { um_write }
83
+ x.report('UM#send') { um_send }
84
+ x.report('UM#send_bundle') { um_send_bundle }
85
+ x.compare!
86
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/uringmachine'
4
+ require_relative '../lib/uringmachine/fiber_scheduler'
5
+ require 'net/http'
6
+
7
+ machine = UringMachine.new
8
+ scheduler = UM::FiberScheduler.new(machine)
9
+ Fiber.set_scheduler scheduler
10
+
11
+ i, o = IO.pipe
12
+
13
+ f1 = Fiber.schedule do
14
+ # sleep 0.4
15
+ # o.write 'Hello, world!'
16
+ # o.close
17
+ end
18
+
19
+ f2 = Fiber.schedule do
20
+ # puts "hi"
21
+ # 10.times do
22
+ # sleep 0.1
23
+ # puts "."
24
+ # end
25
+ end
26
+
27
+ # Fiber.schedule do
28
+ # scheduler.block(:wait)
29
+ # end
30
+
31
+ f3 = Fiber.schedule do
32
+ # message = i.read
33
+ # puts message
34
+ # rescue => e
35
+ # scheduler.p e
36
+ # scheduler.p e.backtrace
37
+ end
38
+
39
+ f4 = Fiber.schedule do
40
+ puts '*' * 40
41
+ # tcp = TCPSocket.new('noteflakes.com', 80)
42
+ # tcp.timeout = 10
43
+ # scheduler.p tcp
44
+ # tcp << "GET / HTTP/1.1\r\nHost: noteflakes.com\r\n\r\n"
45
+ # s = tcp.read
46
+ # scheduler.p s: s
47
+ ret = Net::HTTP.get('noteflakes.com', '/ping')
48
+ scheduler.p ret: ret
49
+ rescue => e
50
+ scheduler.p e
51
+ scheduler.p e.backtrace
52
+ end
53
+
54
+ scheduler.join(f1, f2, f3, f4)
55
+
56
+ __END__
57
+
58
+ stdout_fd = STDOUT.fileno
59
+ stdin_fd = STDIN.fileno
60
+ machine.write(stdout_fd, "Hello, world!\n")
61
+
62
+ loop do
63
+ machine.write(stdout_fd, "Say something: ")
64
+ buf = +''
65
+ res = machine.read(stdin_fd, buf, 8192)
66
+ if res > 0
67
+ machine.write(stdout_fd, "You said: #{buf}")
68
+ else
69
+ break
70
+ end
71
+ end
data/ext/um/um.c CHANGED
@@ -74,6 +74,9 @@ static inline void um_process_cqe(struct um *machine, struct io_uring_cqe *cqe)
74
74
  // );
75
75
 
76
76
  if (op->flags & OP_F_FREE_ON_COMPLETE) {
77
+ if (op->flags & OP_F_TRANSIENT)
78
+ um_op_transient_remove(machine, op);
79
+
77
80
  um_op_free(machine, op);
78
81
  return;
79
82
  }
@@ -249,8 +252,10 @@ inline int um_check_completion(struct um *machine, struct um_op *op) {
249
252
  }
250
253
 
251
254
  inline VALUE um_await(struct um *machine) {
252
- VALUE v = um_fiber_switch(machine);
253
- return raise_if_exception(v);
255
+ VALUE ret = um_fiber_switch(machine);
256
+ RAISE_IF_EXCEPTION(ret);
257
+ RB_GC_GUARD(ret);
258
+ return ret;
254
259
  }
255
260
 
256
261
  inline void um_prep_op(struct um *machine, struct um_op *op, enum op_kind kind, unsigned flags) {
@@ -337,8 +342,9 @@ VALUE um_sleep(struct um *machine, double duration) {
337
342
  ret = DBL2NUM(duration);
338
343
  }
339
344
 
345
+ RAISE_IF_EXCEPTION(ret);
340
346
  RB_GC_GUARD(ret);
341
- return raise_if_exception(ret);
347
+ return ret;
342
348
  }
343
349
 
344
350
  inline VALUE um_read(struct um *machine, int fd, VALUE buffer, int maxlen, int buffer_offset) {
@@ -354,10 +360,11 @@ inline VALUE um_read(struct um *machine, int fd, VALUE buffer, int maxlen, int b
354
360
  ret = INT2NUM(op.result.res);
355
361
 
356
362
  }
357
-
358
363
  RB_GC_GUARD(buffer);
364
+
365
+ RAISE_IF_EXCEPTION(ret);
359
366
  RB_GC_GUARD(ret);
360
- return raise_if_exception(ret);
367
+ return ret;
361
368
  }
362
369
 
363
370
  inline size_t um_read_raw(struct um *machine, int fd, char *buffer, int maxlen) {
@@ -372,7 +379,8 @@ inline size_t um_read_raw(struct um *machine, int fd, char *buffer, int maxlen)
372
379
 
373
380
  }
374
381
 
375
- raise_if_exception(ret);
382
+ RAISE_IF_EXCEPTION(ret);
383
+ RB_GC_GUARD(ret);
376
384
  return 0;
377
385
  }
378
386
 
@@ -390,17 +398,21 @@ VALUE um_write(struct um *machine, int fd, VALUE str, int len) {
390
398
  ret = INT2NUM(op.result.res);
391
399
 
392
400
  RB_GC_GUARD(str);
401
+
402
+ RAISE_IF_EXCEPTION(ret);
393
403
  RB_GC_GUARD(ret);
394
- return raise_if_exception(ret);
404
+ return ret;
395
405
  }
396
406
 
397
407
  VALUE um_write_async(struct um *machine, int fd, VALUE str) {
398
408
  struct um_op *op = um_op_alloc(machine);
399
- um_prep_op(machine, op, OP_WRITE_ASYNC, OP_F_FREE_ON_COMPLETE);
409
+ um_prep_op(machine, op, OP_WRITE_ASYNC, OP_F_TRANSIENT | OP_F_FREE_ON_COMPLETE);
400
410
  RB_OBJ_WRITE(machine->self, &op->value, str);
401
411
 
402
412
  struct io_uring_sqe *sqe = um_get_sqe(machine, op);
403
413
  io_uring_prep_write(sqe, fd, RSTRING_PTR(str), RSTRING_LEN(str), -1);
414
+ um_op_transient_add(machine, op);
415
+
404
416
  return str;
405
417
  }
406
418
 
@@ -414,8 +426,9 @@ VALUE um_close(struct um *machine, int fd) {
414
426
  if (um_check_completion(machine, &op))
415
427
  ret = INT2NUM(fd);
416
428
 
429
+ RAISE_IF_EXCEPTION(ret);
417
430
  RB_GC_GUARD(ret);
418
- return raise_if_exception(ret);
431
+ return ret;
419
432
  }
420
433
 
421
434
  VALUE um_close_async(struct um *machine, int fd) {
@@ -438,8 +451,9 @@ VALUE um_accept(struct um *machine, int fd) {
438
451
  if (um_check_completion(machine, &op))
439
452
  ret = INT2NUM(op.result.res);
440
453
 
454
+ RAISE_IF_EXCEPTION(ret);
441
455
  RB_GC_GUARD(ret);
442
- return raise_if_exception(ret);
456
+ return ret;
443
457
  }
444
458
 
445
459
  VALUE um_socket(struct um *machine, int domain, int type, int protocol, uint flags) {
@@ -452,8 +466,9 @@ VALUE um_socket(struct um *machine, int domain, int type, int protocol, uint fla
452
466
  if (um_check_completion(machine, &op))
453
467
  ret = INT2NUM(op.result.res);
454
468
 
469
+ RAISE_IF_EXCEPTION(ret);
455
470
  RB_GC_GUARD(ret);
456
- return raise_if_exception(ret);
471
+ return ret;
457
472
  }
458
473
 
459
474
  VALUE um_connect(struct um *machine, int fd, const struct sockaddr *addr, socklen_t addrlen) {
@@ -466,8 +481,9 @@ VALUE um_connect(struct um *machine, int fd, const struct sockaddr *addr, sockle
466
481
  if (um_check_completion(machine, &op))
467
482
  ret = INT2NUM(op.result.res);
468
483
 
484
+ RAISE_IF_EXCEPTION(ret);
469
485
  RB_GC_GUARD(ret);
470
- return raise_if_exception(ret);
486
+ return ret;
471
487
  }
472
488
 
473
489
  VALUE um_send(struct um *machine, int fd, VALUE buffer, int len, int flags) {
@@ -481,8 +497,30 @@ VALUE um_send(struct um *machine, int fd, VALUE buffer, int len, int flags) {
481
497
  ret = INT2NUM(op.result.res);
482
498
 
483
499
  RB_GC_GUARD(buffer);
500
+
501
+ RAISE_IF_EXCEPTION(ret);
502
+ RB_GC_GUARD(ret);
503
+ return ret;
504
+ }
505
+
506
+ VALUE um_send_bundle(struct um *machine, int fd, int bgid, VALUE strings) {
507
+ um_add_strings_to_buffer_ring(machine, bgid, strings);
508
+
509
+ struct um_op op;
510
+ um_prep_op(machine, &op, OP_SEND_BUNDLE, 0);
511
+ struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
512
+
513
+ io_uring_prep_send_bundle(sqe, fd, 0, MSG_WAITALL);
514
+ sqe->flags |= IOSQE_BUFFER_SELECT;
515
+ sqe->buf_group = bgid;
516
+
517
+ VALUE ret = um_fiber_switch(machine);
518
+ if (um_check_completion(machine, &op))
519
+ ret = INT2NUM(op.result.res);
520
+
521
+ RAISE_IF_EXCEPTION(ret);
484
522
  RB_GC_GUARD(ret);
485
- return raise_if_exception(ret);
523
+ return ret;
486
524
  }
487
525
 
488
526
  VALUE um_recv(struct um *machine, int fd, VALUE buffer, int maxlen, int flags) {
@@ -499,8 +537,10 @@ VALUE um_recv(struct um *machine, int fd, VALUE buffer, int maxlen, int flags) {
499
537
  }
500
538
 
501
539
  RB_GC_GUARD(buffer);
540
+
541
+ RAISE_IF_EXCEPTION(ret);
502
542
  RB_GC_GUARD(ret);
503
- return raise_if_exception(ret);
543
+ return ret;
504
544
  }
505
545
 
506
546
  VALUE um_bind(struct um *machine, int fd, struct sockaddr *addr, socklen_t addrlen) {
@@ -513,8 +553,9 @@ VALUE um_bind(struct um *machine, int fd, struct sockaddr *addr, socklen_t addrl
513
553
  if (um_check_completion(machine, &op))
514
554
  ret = INT2NUM(op.result.res);
515
555
 
556
+ RAISE_IF_EXCEPTION(ret);
516
557
  RB_GC_GUARD(ret);
517
- return raise_if_exception(ret);
558
+ return ret;
518
559
  }
519
560
 
520
561
  VALUE um_listen(struct um *machine, int fd, int backlog) {
@@ -527,8 +568,9 @@ VALUE um_listen(struct um *machine, int fd, int backlog) {
527
568
  if (um_check_completion(machine, &op))
528
569
  ret = INT2NUM(op.result.res);
529
570
 
571
+ RAISE_IF_EXCEPTION(ret);
530
572
  RB_GC_GUARD(ret);
531
- return raise_if_exception(ret);
573
+ return ret;
532
574
  }
533
575
 
534
576
  VALUE um_getsockopt(struct um *machine, int fd, int level, int opt) {
@@ -552,8 +594,9 @@ VALUE um_getsockopt(struct um *machine, int fd, int level, int opt) {
552
594
  ret = INT2NUM(value);
553
595
  #endif
554
596
 
597
+ RAISE_IF_EXCEPTION(ret);
555
598
  RB_GC_GUARD(ret);
556
- return raise_if_exception(ret);
599
+ return ret;
557
600
  }
558
601
 
559
602
  VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value) {
@@ -575,8 +618,9 @@ VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value) {
575
618
  ret = INT2NUM(0);
576
619
  #endif
577
620
 
621
+ RAISE_IF_EXCEPTION(ret);
578
622
  RB_GC_GUARD(ret);
579
- return raise_if_exception(ret);
623
+ return ret;
580
624
  }
581
625
 
582
626
  VALUE um_shutdown(struct um *machine, int fd, int how) {
@@ -591,14 +635,14 @@ VALUE um_shutdown(struct um *machine, int fd, int how) {
591
635
  if (um_check_completion(machine, &op))
592
636
  ret = INT2NUM(op.result.res);
593
637
 
638
+ RAISE_IF_EXCEPTION(ret);
594
639
  RB_GC_GUARD(ret);
595
- return raise_if_exception(ret);
640
+ return ret;
596
641
  }
597
642
 
598
643
  VALUE um_shutdown_async(struct um *machine, int fd, int how) {
599
644
  struct um_op *op = um_op_alloc(machine);
600
645
  um_prep_op(machine, op, OP_SHUTDOWN_ASYNC, OP_F_FREE_ON_COMPLETE);
601
-
602
646
  struct io_uring_sqe *sqe = um_get_sqe(machine, op);
603
647
  io_uring_prep_shutdown(sqe, fd, how);
604
648
 
@@ -615,8 +659,24 @@ VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode) {
615
659
  if (um_check_completion(machine, &op))
616
660
  ret = INT2NUM(op.result.res);
617
661
 
662
+ RAISE_IF_EXCEPTION(ret);
663
+ RB_GC_GUARD(ret);
664
+ return ret;
665
+ }
666
+
667
+ VALUE um_poll(struct um *machine, int fd, unsigned mask) {
668
+ struct um_op op;
669
+ um_prep_op(machine, &op, OP_POLL, 0);
670
+ struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
671
+ io_uring_prep_poll_add(sqe, fd, mask);
672
+
673
+ VALUE ret = um_fiber_switch(machine);
674
+ if (um_check_completion(machine, &op))
675
+ ret = INT2NUM(op.result.res);
676
+
677
+ RAISE_IF_EXCEPTION(ret);
618
678
  RB_GC_GUARD(ret);
619
- return raise_if_exception(ret);
679
+ return ret;
620
680
  }
621
681
 
622
682
  VALUE um_waitpid(struct um *machine, int pid, int options) {
@@ -631,8 +691,8 @@ VALUE um_waitpid(struct um *machine, int pid, int options) {
631
691
  if (um_check_completion(machine, &op))
632
692
  ret = INT2NUM(op.result.res);
633
693
 
694
+ RAISE_IF_EXCEPTION(ret);
634
695
  RB_GC_GUARD(ret);
635
- raise_if_exception(ret);
636
696
 
637
697
  return rb_ary_new_from_args(2, INT2NUM(infop.si_pid), INT2NUM(infop.si_status));
638
698
  }
@@ -661,24 +721,23 @@ VALUE statx_to_hash(struct statx *stat) {
661
721
  }
662
722
 
663
723
  VALUE um_statx(struct um *machine, int dirfd, VALUE path, int flags, unsigned int mask) {
724
+ static char empty_path[] = "";
725
+
664
726
  struct um_op op;
665
727
  um_prep_op(machine, &op, OP_STATX, 0);
666
728
  struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
667
729
 
730
+ char *path_ptr = NIL_P(path) ? empty_path : StringValueCStr(path);
668
731
  struct statx stat;
669
732
  memset(&stat, 0, sizeof(stat));
670
-
671
- if (NIL_P(path))
672
- path = rb_str_new_literal("");
673
-
674
- io_uring_prep_statx(sqe, dirfd, StringValueCStr(path), flags, mask, &stat);
733
+ io_uring_prep_statx(sqe, dirfd, path_ptr, flags, mask, &stat);
675
734
 
676
735
  VALUE ret = um_fiber_switch(machine);
677
736
  if (um_check_completion(machine, &op))
678
737
  ret = INT2NUM(op.result.res);
679
738
 
739
+ RAISE_IF_EXCEPTION(ret);
680
740
  RB_GC_GUARD(ret);
681
- raise_if_exception(ret);
682
741
 
683
742
  return statx_to_hash(&stat);
684
743
  }
@@ -694,8 +753,11 @@ VALUE accept_each_start(VALUE arg) {
694
753
 
695
754
  while (true) {
696
755
  VALUE ret = um_fiber_switch(ctx->machine);
697
- if (!um_op_completed_p(ctx->op))
698
- return raise_if_exception(ret);
756
+ if (!um_op_completed_p(ctx->op)) {
757
+ RAISE_IF_EXCEPTION(ret);
758
+ return ret;
759
+ }
760
+ RB_GC_GUARD(ret);
699
761
 
700
762
  int more = false;
701
763
  struct um_op_result *result = &ctx->op->result;
@@ -764,8 +826,11 @@ int um_read_each_singleshot_loop(struct op_ctx *ctx) {
764
826
  rb_yield(buf);
765
827
  RB_GC_GUARD(buf);
766
828
  }
767
- else
768
- return raise_if_exception(ret);
829
+ else {
830
+ RAISE_IF_EXCEPTION(ret);
831
+ return ret;
832
+ }
833
+ RB_GC_GUARD(ret);
769
834
  }
770
835
  }
771
836
 
@@ -813,8 +878,11 @@ VALUE read_recv_each_start(VALUE arg) {
813
878
 
814
879
  while (true) {
815
880
  VALUE ret = um_fiber_switch(ctx->machine);
816
- if (!um_op_completed_p(ctx->op))
817
- return raise_if_exception(ret);
881
+ if (!um_op_completed_p(ctx->op)) {
882
+ RAISE_IF_EXCEPTION(ret);
883
+ return ret;
884
+ }
885
+ RB_GC_GUARD(ret);
818
886
 
819
887
  int more = false;
820
888
  struct um_op_result *result = &ctx->op->result;
@@ -861,8 +929,11 @@ VALUE periodically_start(VALUE arg) {
861
929
 
862
930
  while (true) {
863
931
  VALUE ret = um_fiber_switch(ctx->machine);
864
- if (!um_op_completed_p(ctx->op))
865
- return raise_if_exception(ret);
932
+ if (!um_op_completed_p(ctx->op)) {
933
+ RAISE_IF_EXCEPTION(ret);
934
+ return ret;
935
+ }
936
+ RB_GC_GUARD(ret);
866
937
 
867
938
  int more = false;
868
939
  struct um_op_result *result = &ctx->op->result;
data/ext/um/um.h CHANGED
@@ -36,6 +36,7 @@ enum op_kind {
36
36
  OP_ACCEPT,
37
37
  OP_RECV,
38
38
  OP_SEND,
39
+ OP_SEND_BUNDLE,
39
40
  OP_SOCKET,
40
41
  OP_CONNECT,
41
42
  OP_BIND,
@@ -44,7 +45,8 @@ enum op_kind {
44
45
  OP_SETSOCKOPT,
45
46
  OP_SHUTDOWN,
46
47
  OP_SHUTDOWN_ASYNC,
47
-
48
+
49
+ OP_POLL,
48
50
  OP_WAITPID,
49
51
 
50
52
  OP_FUTEX_WAIT,
@@ -202,7 +204,7 @@ double um_timestamp_to_double(__s64 tv_sec, __u32 tv_nsec);
202
204
  int um_value_is_exception_p(VALUE v);
203
205
  VALUE um_raise_exception(VALUE v);
204
206
 
205
- #define raise_if_exception(v) (um_value_is_exception_p(v) ? um_raise_exception(v) : v)
207
+ #define RAISE_IF_EXCEPTION(v) if (um_value_is_exception_p(v)) { um_raise_exception(v); }
206
208
 
207
209
  void um_prep_op(struct um *machine, struct um_op *op, enum op_kind kind, unsigned flags);
208
210
  void um_raise_on_error_result(int result);
@@ -210,6 +212,7 @@ void * um_prepare_read_buffer(VALUE buffer, unsigned len, int ofs);
210
212
  void um_update_read_buffer(struct um *machine, VALUE buffer, int buffer_offset, __s32 result, __u32 flags);
211
213
  int um_setup_buffer_ring(struct um *machine, unsigned size, unsigned count);
212
214
  VALUE um_get_string_from_buffer_ring(struct um *machine, int bgid, __s32 result, __u32 flags);
215
+ void um_add_strings_to_buffer_ring(struct um *machine, int bgid, VALUE strings);
213
216
 
214
217
  struct io_uring_sqe *um_get_sqe(struct um *machine, struct um_op *op);
215
218
 
@@ -233,6 +236,7 @@ VALUE um_write(struct um *machine, int fd, VALUE str, int len);
233
236
  VALUE um_close(struct um *machine, int fd);
234
237
  VALUE um_close_async(struct um *machine, int fd);
235
238
  VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode);
239
+ VALUE um_poll(struct um *machine, int fd, unsigned mask);
236
240
  VALUE um_waitpid(struct um *machine, int pid, int options);
237
241
  VALUE um_statx(struct um *machine, int dirfd, VALUE path, int flags, unsigned int mask);
238
242
  VALUE um_write_async(struct um *machine, int fd, VALUE str);
@@ -242,6 +246,7 @@ VALUE um_accept_each(struct um *machine, int fd);
242
246
  VALUE um_socket(struct um *machine, int domain, int type, int protocol, uint flags);
243
247
  VALUE um_connect(struct um *machine, int fd, const struct sockaddr *addr, socklen_t addrlen);
244
248
  VALUE um_send(struct um *machine, int fd, VALUE buffer, int len, int flags);
249
+ VALUE um_send_bundle(struct um *machine, int fd, int bgid, VALUE strings);
245
250
  VALUE um_recv(struct um *machine, int fd, VALUE buffer, int maxlen, int flags);
246
251
  VALUE um_recv_each(struct um *machine, int fd, int bgid, int flags);
247
252
  VALUE um_bind(struct um *machine, int fd, struct sockaddr *addr, socklen_t addrlen);
data/ext/um/um_async_op.c CHANGED
@@ -30,7 +30,8 @@ VALUE um_async_op_await(struct um_async_op *async_op) {
30
30
  if (!um_op_completed_p(async_op->op))
31
31
  um_cancel_and_wait(async_op->machine, async_op->op);
32
32
 
33
- raise_if_exception(ret);
33
+ RAISE_IF_EXCEPTION(ret);
34
+ RB_GC_GUARD(ret);
34
35
  return INT2NUM(async_op->op->result.res);
35
36
  }
36
37
 
data/ext/um/um_class.c CHANGED
@@ -193,6 +193,22 @@ VALUE UM_send(VALUE self, VALUE fd, VALUE buffer, VALUE len, VALUE flags) {
193
193
  return um_send(machine, NUM2INT(fd), buffer, NUM2INT(len), NUM2INT(flags));
194
194
  }
195
195
 
196
+ VALUE UM_send_bundle(int argc, VALUE *argv, VALUE self) {
197
+ struct um *machine = um_get_machine(self);
198
+ VALUE fd;
199
+ VALUE bgid;
200
+ VALUE strings;
201
+ rb_scan_args(argc, argv, "2*", &fd, &bgid, &strings);
202
+
203
+ if (RARRAY_LEN(strings) == 1) {
204
+ VALUE first = rb_ary_entry(strings, 0);
205
+ if (TYPE(first) == T_ARRAY)
206
+ strings = first;
207
+ }
208
+
209
+ return um_send_bundle(machine, NUM2INT(fd), NUM2INT(bgid), strings);
210
+ }
211
+
196
212
  VALUE UM_recv(VALUE self, VALUE fd, VALUE buffer, VALUE maxlen, VALUE flags) {
197
213
  struct um *machine = um_get_machine(self);
198
214
  return um_recv(machine, NUM2INT(fd), buffer, NUM2INT(maxlen), NUM2INT(flags));
@@ -311,6 +327,11 @@ VALUE UM_open(VALUE self, VALUE pathname, VALUE flags) {
311
327
  return fd;
312
328
  }
313
329
 
330
+ VALUE UM_poll(VALUE self, VALUE fd, VALUE mask) {
331
+ struct um *machine = um_get_machine(self);
332
+ return um_poll(machine, NUM2INT(fd), NUM2UINT(mask));
333
+ }
334
+
314
335
  VALUE UM_waitpid(VALUE self, VALUE pid, VALUE options) {
315
336
  struct um *machine = um_get_machine(self);
316
337
  return um_waitpid(machine, NUM2INT(pid), NUM2INT(options));
@@ -366,6 +387,7 @@ void Init_UM(void) {
366
387
  rb_define_method(cUM, "write_async", UM_write_async, 2);
367
388
  rb_define_method(cUM, "statx", UM_statx, 4);
368
389
 
390
+ rb_define_method(cUM, "poll", UM_poll, 2);
369
391
  rb_define_method(cUM, "waitpid", UM_waitpid, 2);
370
392
 
371
393
  rb_define_method(cUM, "accept", UM_accept, 1);
@@ -377,6 +399,7 @@ void Init_UM(void) {
377
399
  rb_define_method(cUM, "recv", UM_recv, 4);
378
400
  rb_define_method(cUM, "recv_each", UM_recv_each, 3);
379
401
  rb_define_method(cUM, "send", UM_send, 4);
402
+ rb_define_method(cUM, "send_bundle", UM_send_bundle, -1);
380
403
  rb_define_method(cUM, "setsockopt", UM_setsockopt, 4);
381
404
  rb_define_method(cUM, "socket", UM_socket, 4);
382
405
  rb_define_method(cUM, "shutdown", UM_shutdown, 2);