uringmachine 0.20.0 → 0.21.0
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/.github/workflows/test.yml +3 -4
- data/CHANGELOG.md +20 -0
- data/TODO.md +0 -38
- data/examples/bm_queue.rb +2 -1
- data/examples/bm_write.rb +4 -1
- data/ext/um/extconf.rb +1 -1
- data/ext/um/um.c +269 -49
- data/ext/um/um.h +48 -21
- data/ext/um/um_async_op.c +1 -1
- data/ext/um/um_class.c +89 -13
- data/ext/um/um_op.c +37 -0
- data/ext/um/um_sync.c +8 -14
- data/grant-2025/journal.md +125 -1
- data/grant-2025/tasks.md +102 -33
- data/lib/uringmachine/fiber_scheduler.rb +191 -64
- data/lib/uringmachine/version.rb +1 -1
- data/test/test_fiber_scheduler.rb +519 -17
- data/test/test_um.rb +298 -23
- data/uringmachine.gemspec +5 -5
- data/vendor/liburing/src/include/liburing/io_uring.h +1 -0
- data/vendor/liburing/src/include/liburing.h +13 -0
- data/vendor/liburing/src/liburing-ffi.map +1 -0
- data/vendor/liburing/test/bind-listen.c +175 -13
- data/vendor/liburing/test/read-write.c +4 -4
- data/vendor/liburing/test/ringbuf-read.c +4 -4
- data/vendor/liburing/test/send_recv.c +8 -7
- metadata +15 -15
|
@@ -22,7 +22,7 @@ static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec)
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
static const char *magic = "Hello World!";
|
|
25
|
-
static
|
|
25
|
+
static bool no_getsockname = false;
|
|
26
26
|
|
|
27
27
|
enum {
|
|
28
28
|
SRV_INDEX = 0,
|
|
@@ -74,18 +74,82 @@ static int connect_client(struct io_uring *ring, unsigned short peer_port)
|
|
|
74
74
|
return T_SETUP_OK;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
/*
|
|
78
|
+
* getsockname was added to the kernel a few releases after bind/listen.
|
|
79
|
+
* In order to provide a backward-compatible test, fallback to
|
|
80
|
+
* non-io-uring if we are on an older kernel, allowing the test to
|
|
81
|
+
* continue.
|
|
82
|
+
*/
|
|
83
|
+
static int do_getsockname(struct io_uring *ring, int direct_socket,
|
|
84
|
+
int peer, struct sockaddr *saddr,
|
|
85
|
+
socklen_t *saddr_len)
|
|
86
|
+
{
|
|
87
|
+
struct io_uring_sqe *sqe;
|
|
88
|
+
struct io_uring_cqe *cqe;
|
|
89
|
+
int res = 0, fd;
|
|
90
|
+
|
|
91
|
+
if (!no_getsockname) {
|
|
92
|
+
/* attempt io_uring. Command might not exist */
|
|
93
|
+
sqe = io_uring_get_sqe(ring);
|
|
94
|
+
io_uring_prep_cmd_getsockname(sqe, direct_socket,
|
|
95
|
+
saddr, saddr_len, peer);
|
|
96
|
+
sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
|
|
97
|
+
io_uring_submit(ring);
|
|
98
|
+
io_uring_wait_cqe(ring, &cqe);
|
|
99
|
+
res = cqe->res;
|
|
100
|
+
io_uring_cqe_seen(ring, cqe);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (no_getsockname || res == -ENOTSUP) {
|
|
104
|
+
/*
|
|
105
|
+
* Older kernel. install the fd and use the getsockname
|
|
106
|
+
* syscall.
|
|
107
|
+
*/
|
|
108
|
+
no_getsockname = true;
|
|
109
|
+
|
|
110
|
+
sqe = io_uring_get_sqe(ring);
|
|
111
|
+
io_uring_prep_fixed_fd_install(sqe, direct_socket, 0);
|
|
112
|
+
io_uring_submit(ring);
|
|
113
|
+
io_uring_wait_cqe(ring, &cqe);
|
|
114
|
+
fd = cqe->res;
|
|
115
|
+
io_uring_cqe_seen(ring, cqe);
|
|
116
|
+
|
|
117
|
+
if (fd < 0) {
|
|
118
|
+
fprintf(stderr, "installing direct fd failed. %d\n",
|
|
119
|
+
cqe->res);
|
|
120
|
+
return T_EXIT_FAIL;
|
|
121
|
+
}
|
|
122
|
+
if (peer)
|
|
123
|
+
res = getpeername(fd, saddr, saddr_len);
|
|
124
|
+
else
|
|
125
|
+
res = getsockname(fd, saddr, saddr_len);
|
|
126
|
+
|
|
127
|
+
if (res) {
|
|
128
|
+
fprintf(stderr, "get%sname syscall failed. %d\n",
|
|
129
|
+
peer? "peer":"sock", errno);
|
|
130
|
+
return T_EXIT_FAIL;
|
|
131
|
+
}
|
|
132
|
+
close(fd);
|
|
133
|
+
} else if (res < 0) {
|
|
134
|
+
fprintf(stderr, "getsockname server failed. %d\n", cqe->res);
|
|
135
|
+
return T_EXIT_FAIL;
|
|
136
|
+
}
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static int setup_srv(struct io_uring *ring)
|
|
78
141
|
{
|
|
142
|
+
struct sockaddr_in server_addr;
|
|
79
143
|
struct io_uring_sqe *sqe;
|
|
80
144
|
struct io_uring_cqe *cqe;
|
|
81
145
|
struct __kernel_timespec ts;
|
|
82
146
|
int ret, val, submitted;
|
|
83
147
|
unsigned head;
|
|
84
148
|
|
|
85
|
-
memset(server_addr, 0, sizeof(struct sockaddr_in));
|
|
86
|
-
server_addr
|
|
87
|
-
server_addr
|
|
88
|
-
server_addr
|
|
149
|
+
memset(&server_addr, 0, sizeof(struct sockaddr_in));
|
|
150
|
+
server_addr.sin_family = AF_INET;
|
|
151
|
+
server_addr.sin_port = htons(0);
|
|
152
|
+
server_addr.sin_addr.s_addr = htons(INADDR_ANY);
|
|
89
153
|
|
|
90
154
|
sqe = io_uring_get_sqe(ring);
|
|
91
155
|
io_uring_prep_socket_direct(sqe, AF_INET, SOCK_STREAM, 0, SRV_INDEX, 0);
|
|
@@ -98,7 +162,7 @@ static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
|
|
|
98
162
|
sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
|
|
99
163
|
|
|
100
164
|
sqe = io_uring_get_sqe(ring);
|
|
101
|
-
io_uring_prep_bind(sqe, SRV_INDEX, (struct sockaddr *) server_addr,
|
|
165
|
+
io_uring_prep_bind(sqe, SRV_INDEX, (struct sockaddr *) &server_addr,
|
|
102
166
|
sizeof(struct sockaddr_in));
|
|
103
167
|
sqe->flags |= IOSQE_FIXED_FILE | IOSQE_IO_LINK;
|
|
104
168
|
|
|
@@ -132,12 +196,13 @@ static int setup_srv(struct io_uring *ring, struct sockaddr_in *server_addr)
|
|
|
132
196
|
|
|
133
197
|
static int test_good_server(unsigned int ring_flags)
|
|
134
198
|
{
|
|
135
|
-
struct sockaddr_in
|
|
199
|
+
struct sockaddr_in saddr = {};
|
|
200
|
+
socklen_t saddr_len = sizeof(saddr);
|
|
136
201
|
struct __kernel_timespec ts;
|
|
137
202
|
struct io_uring_sqe *sqe;
|
|
138
203
|
struct io_uring_cqe *cqe;
|
|
139
204
|
struct io_uring ring;
|
|
140
|
-
int ret;
|
|
205
|
+
int ret, port;
|
|
141
206
|
int fds[3];
|
|
142
207
|
char buf[1024];
|
|
143
208
|
|
|
@@ -155,18 +220,22 @@ static int test_good_server(unsigned int ring_flags)
|
|
|
155
220
|
return T_SETUP_SKIP;
|
|
156
221
|
}
|
|
157
222
|
|
|
158
|
-
ret = setup_srv(&ring
|
|
223
|
+
ret = setup_srv(&ring);
|
|
159
224
|
if (ret != T_SETUP_OK) {
|
|
160
225
|
fprintf(stderr, "srv startup failed.\n");
|
|
161
226
|
return T_EXIT_FAIL;
|
|
162
227
|
}
|
|
163
228
|
|
|
164
|
-
if (
|
|
229
|
+
if (do_getsockname(&ring, SRV_INDEX, 0, (struct sockaddr*) &saddr,
|
|
230
|
+
&saddr_len))
|
|
231
|
+
return T_EXIT_FAIL;
|
|
232
|
+
|
|
233
|
+
if (connect_client(&ring, saddr.sin_port) != T_SETUP_OK) {
|
|
165
234
|
fprintf(stderr, "cli startup failed.\n");
|
|
166
235
|
return T_SETUP_SKIP;
|
|
167
236
|
}
|
|
168
237
|
|
|
169
|
-
/* Wait for a
|
|
238
|
+
/* Wait for a connection */
|
|
170
239
|
sqe = io_uring_get_sqe(&ring);
|
|
171
240
|
io_uring_prep_accept_direct(sqe, SRV_INDEX, NULL, NULL, 0, CONN_INDEX);
|
|
172
241
|
sqe->flags |= IOSQE_FIXED_FILE;
|
|
@@ -179,6 +248,22 @@ static int test_good_server(unsigned int ring_flags)
|
|
|
179
248
|
}
|
|
180
249
|
io_uring_cqe_seen(&ring, cqe);
|
|
181
250
|
|
|
251
|
+
/* Test that getsockname on the peer (getpeername) yields a
|
|
252
|
+
* sane result.
|
|
253
|
+
*/
|
|
254
|
+
port = saddr.sin_port;
|
|
255
|
+
saddr.sin_port = 0;
|
|
256
|
+
if (do_getsockname(&ring, CLI_INDEX, 1,
|
|
257
|
+
(struct sockaddr*)&saddr, &saddr_len))
|
|
258
|
+
return T_EXIT_FAIL;
|
|
259
|
+
|
|
260
|
+
if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK) ||
|
|
261
|
+
saddr.sin_port != port) {
|
|
262
|
+
fprintf(stderr, "getsockname peer got wrong address: %s:%d\n",
|
|
263
|
+
inet_ntoa(saddr.sin_addr), saddr.sin_port);
|
|
264
|
+
return T_EXIT_FAIL;
|
|
265
|
+
}
|
|
266
|
+
|
|
182
267
|
sqe = io_uring_get_sqe(&ring);
|
|
183
268
|
io_uring_prep_recv(sqe, CONN_INDEX, buf, sizeof(buf), 0);
|
|
184
269
|
sqe->flags |= IOSQE_FIXED_FILE;
|
|
@@ -355,6 +440,77 @@ fail:
|
|
|
355
440
|
return ret;
|
|
356
441
|
}
|
|
357
442
|
|
|
443
|
+
static int test_bad_sockname(void)
|
|
444
|
+
{
|
|
445
|
+
struct sockaddr_in saddr;
|
|
446
|
+
socklen_t saddr_len;
|
|
447
|
+
struct io_uring_sqe *sqe;
|
|
448
|
+
struct io_uring_cqe *cqe;
|
|
449
|
+
struct io_uring ring;
|
|
450
|
+
int sock = -1, err;
|
|
451
|
+
int ret = T_EXIT_FAIL;
|
|
452
|
+
|
|
453
|
+
memset(&saddr, 0, sizeof(struct sockaddr_in));
|
|
454
|
+
saddr.sin_family = AF_INET;
|
|
455
|
+
saddr.sin_port = htons(8001);
|
|
456
|
+
saddr.sin_addr.s_addr = htons(INADDR_ANY);
|
|
457
|
+
|
|
458
|
+
err = t_create_ring(1, &ring, 0);
|
|
459
|
+
if (err < 0) {
|
|
460
|
+
fprintf(stderr, "queue_init: %d\n", err);
|
|
461
|
+
return T_SETUP_SKIP;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
465
|
+
if (sock < 0) {
|
|
466
|
+
perror("socket");
|
|
467
|
+
goto fail;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
err = t_bind_ephemeral_port(sock, &saddr);
|
|
471
|
+
if (err) {
|
|
472
|
+
fprintf(stderr, "bind: %s\n", strerror(-err));
|
|
473
|
+
goto fail;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/* getsockname on a !socket fd. with getsockname(2), this would
|
|
477
|
+
* return -ENOTSOCK, but we can't do it in an io_uring_cmd.
|
|
478
|
+
*/
|
|
479
|
+
sqe = io_uring_get_sqe(&ring);
|
|
480
|
+
saddr_len = sizeof(saddr);
|
|
481
|
+
io_uring_prep_cmd_getsockname(sqe, 1, (struct sockaddr*)&saddr, &saddr_len, 0);
|
|
482
|
+
err = io_uring_submit(&ring);
|
|
483
|
+
if (err < 0)
|
|
484
|
+
goto fail;
|
|
485
|
+
err = io_uring_wait_cqe(&ring, &cqe);
|
|
486
|
+
if (err)
|
|
487
|
+
goto fail;
|
|
488
|
+
if (cqe->res != -ENOTSUP)
|
|
489
|
+
goto fail;
|
|
490
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
491
|
+
|
|
492
|
+
/* getsockname with weird parameters */
|
|
493
|
+
sqe = io_uring_get_sqe(&ring);
|
|
494
|
+
io_uring_prep_cmd_getsockname(sqe, sock, (struct sockaddr*)&saddr,
|
|
495
|
+
&saddr_len, 3);
|
|
496
|
+
err = io_uring_submit(&ring);
|
|
497
|
+
if (err < 0)
|
|
498
|
+
goto fail;
|
|
499
|
+
err = io_uring_wait_cqe(&ring, &cqe);
|
|
500
|
+
if (err)
|
|
501
|
+
goto fail;
|
|
502
|
+
if (cqe->res != -EINVAL)
|
|
503
|
+
goto fail;
|
|
504
|
+
io_uring_cqe_seen(&ring, cqe);
|
|
505
|
+
|
|
506
|
+
ret = T_EXIT_PASS;
|
|
507
|
+
fail:
|
|
508
|
+
io_uring_queue_exit(&ring);
|
|
509
|
+
if (sock != -1)
|
|
510
|
+
close(sock);
|
|
511
|
+
return ret;
|
|
512
|
+
}
|
|
513
|
+
|
|
358
514
|
int main(int argc, char *argv[])
|
|
359
515
|
{
|
|
360
516
|
struct io_uring_probe *probe;
|
|
@@ -403,6 +559,12 @@ int main(int argc, char *argv[])
|
|
|
403
559
|
fprintf(stderr, "bad listen failed\n");
|
|
404
560
|
return T_EXIT_FAIL;
|
|
405
561
|
}
|
|
406
|
-
|
|
562
|
+
if (!no_getsockname) {
|
|
563
|
+
ret = test_bad_sockname();
|
|
564
|
+
if (ret) {
|
|
565
|
+
fprintf(stderr, "bad sockname failed\n");
|
|
566
|
+
return T_EXIT_FAIL;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
407
569
|
return T_EXIT_PASS;
|
|
408
570
|
}
|
|
@@ -462,7 +462,7 @@ static int test_buf_select_short(const char *filename, int nonvec)
|
|
|
462
462
|
}
|
|
463
463
|
|
|
464
464
|
exp_len = 0;
|
|
465
|
-
for (i = 0; i < BUFFERS; i++) {
|
|
465
|
+
for (i = 0; i < 2 * BUFFERS; i++) {
|
|
466
466
|
sqe = io_uring_get_sqe(&ring);
|
|
467
467
|
io_uring_prep_provide_buffers(sqe, vecs[i].iov_base,
|
|
468
468
|
vecs[i].iov_len / 2, 1, 1, i);
|
|
@@ -471,12 +471,12 @@ static int test_buf_select_short(const char *filename, int nonvec)
|
|
|
471
471
|
}
|
|
472
472
|
|
|
473
473
|
ret = io_uring_submit(&ring);
|
|
474
|
-
if (ret != BUFFERS) {
|
|
474
|
+
if (ret != BUFFERS * 2) {
|
|
475
475
|
fprintf(stderr, "submit: %d\n", ret);
|
|
476
476
|
return -1;
|
|
477
477
|
}
|
|
478
478
|
|
|
479
|
-
for (i = 0; i < BUFFERS; i++) {
|
|
479
|
+
for (i = 0; i < BUFFERS * 2; i++) {
|
|
480
480
|
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
481
481
|
if (cqe->res < 0) {
|
|
482
482
|
fprintf(stderr, "cqe->res=%d\n", cqe->res);
|
|
@@ -935,7 +935,7 @@ int main(int argc, char *argv[])
|
|
|
935
935
|
|
|
936
936
|
signal(SIGXFSZ, SIG_IGN);
|
|
937
937
|
|
|
938
|
-
vecs = t_create_buffers(BUFFERS, BS);
|
|
938
|
+
vecs = t_create_buffers(2 * BUFFERS, BS);
|
|
939
939
|
|
|
940
940
|
/* if we don't have nonvec read, skip testing that */
|
|
941
941
|
nr = has_nonvec_read() ? 64 : 32;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
#include "helpers.h"
|
|
15
15
|
|
|
16
16
|
#define BUF_SIZE 4096
|
|
17
|
-
#define NR_BUFS
|
|
17
|
+
#define NR_BUFS 128
|
|
18
18
|
#define FSIZE (BUF_SIZE * NR_BUFS)
|
|
19
19
|
|
|
20
20
|
#define BR_MASK (NR_BUFS - 1)
|
|
@@ -87,7 +87,7 @@ static int test(const char *filename, int dio, int async)
|
|
|
87
87
|
}
|
|
88
88
|
io_uring_buf_ring_advance(br, NR_BUFS);
|
|
89
89
|
|
|
90
|
-
for (i = 0; i < NR_BUFS; i++) {
|
|
90
|
+
for (i = 0; i < NR_BUFS / 2; i++) {
|
|
91
91
|
sqe = io_uring_get_sqe(&ring);
|
|
92
92
|
io_uring_prep_read(sqe, fd, NULL, BUF_SIZE, i * BUF_SIZE);
|
|
93
93
|
sqe->buf_group = 1;
|
|
@@ -98,12 +98,12 @@ static int test(const char *filename, int dio, int async)
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
ret = io_uring_submit(&ring);
|
|
101
|
-
if (ret != NR_BUFS) {
|
|
101
|
+
if (ret != NR_BUFS / 2) {
|
|
102
102
|
fprintf(stderr, "submit: %d\n", ret);
|
|
103
103
|
return 1;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
for (i = 0; i < NR_BUFS; i++) {
|
|
106
|
+
for (i = 0; i < NR_BUFS / 2; i++) {
|
|
107
107
|
int bid, ud;
|
|
108
108
|
|
|
109
109
|
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include <stdlib.h>
|
|
8
8
|
#include <string.h>
|
|
9
9
|
#include <unistd.h>
|
|
10
|
+
#include <inttypes.h>
|
|
10
11
|
#include <arpa/inet.h>
|
|
11
12
|
#include <sys/types.h>
|
|
12
13
|
#include <sys/socket.h>
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
|
|
18
19
|
#define MAX_MSG 4096
|
|
19
20
|
|
|
20
|
-
static
|
|
21
|
+
static uint64_t str[MAX_MSG / sizeof(uint64_t)];
|
|
21
22
|
|
|
22
23
|
#define PORT 10202
|
|
23
24
|
#define HOST "127.0.0.1"
|
|
@@ -88,7 +89,7 @@ err:
|
|
|
88
89
|
static int do_recv(struct io_uring *ring, struct iovec *iov, int enobufs)
|
|
89
90
|
{
|
|
90
91
|
struct io_uring_cqe *cqe;
|
|
91
|
-
|
|
92
|
+
uint64_t *ptr;
|
|
92
93
|
int i, ret;
|
|
93
94
|
|
|
94
95
|
ret = io_uring_wait_cqe(ring, &cqe);
|
|
@@ -118,10 +119,10 @@ static int do_recv(struct io_uring *ring, struct iovec *iov, int enobufs)
|
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
ptr = iov->iov_base;
|
|
121
|
-
for (i = 0; i < MAX_MSG / sizeof(
|
|
122
|
+
for (i = 0; i < MAX_MSG / sizeof(uint64_t); i++) {
|
|
122
123
|
if (ptr[i] == str[i])
|
|
123
124
|
continue;
|
|
124
|
-
fprintf(stderr, "data mismatch at %d: %
|
|
125
|
+
fprintf(stderr, "data mismatch at %d: %llu\n", i, (unsigned long long) ptr[i]);
|
|
125
126
|
goto err;
|
|
126
127
|
}
|
|
127
128
|
|
|
@@ -224,7 +225,7 @@ retry:
|
|
|
224
225
|
sqe = io_uring_get_sqe(&ring);
|
|
225
226
|
if (vec) {
|
|
226
227
|
size_t total = MAX_MSG;
|
|
227
|
-
|
|
228
|
+
uint64_t *ptr = str;
|
|
228
229
|
int i, nvecs;
|
|
229
230
|
|
|
230
231
|
if (!big_vec) {
|
|
@@ -239,7 +240,7 @@ retry:
|
|
|
239
240
|
for (i = 0; i < 32; i++) {
|
|
240
241
|
vecs[i].iov_base = ptr;
|
|
241
242
|
vecs[i].iov_len = total;
|
|
242
|
-
ptr += total / sizeof(
|
|
243
|
+
ptr += total / sizeof(uint64_t);
|
|
243
244
|
}
|
|
244
245
|
nvecs = 32;
|
|
245
246
|
}
|
|
@@ -371,7 +372,7 @@ int main(int argc, char *argv[])
|
|
|
371
372
|
if (argc > 1)
|
|
372
373
|
return T_EXIT_SKIP;
|
|
373
374
|
|
|
374
|
-
for (i = 0; i < MAX_MSG / sizeof(
|
|
375
|
+
for (i = 0; i < MAX_MSG / sizeof(uint64_t); i++)
|
|
375
376
|
str[i] = i + 1;
|
|
376
377
|
|
|
377
378
|
ret = test_invalid();
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: uringmachine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.21.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sharon Rosner
|
|
@@ -13,56 +13,56 @@ dependencies:
|
|
|
13
13
|
name: rake-compiler
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- -
|
|
16
|
+
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 1.
|
|
18
|
+
version: 1.3.0
|
|
19
19
|
type: :development
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
|
-
- -
|
|
23
|
+
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 1.
|
|
25
|
+
version: 1.3.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: minitest
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
|
-
- -
|
|
30
|
+
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 5.
|
|
32
|
+
version: 5.26.2
|
|
33
33
|
type: :development
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
|
-
- -
|
|
37
|
+
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 5.
|
|
39
|
+
version: 5.26.2
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: benchmark-ips
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
|
-
- -
|
|
44
|
+
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
46
|
version: 2.14.0
|
|
47
47
|
type: :development
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
|
-
- -
|
|
51
|
+
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
53
|
version: 2.14.0
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: http_parser.rb
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
|
-
- -
|
|
58
|
+
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
60
|
version: 0.8.0
|
|
61
61
|
type: :development
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
|
-
- -
|
|
65
|
+
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
67
|
version: 0.8.0
|
|
68
68
|
email: sharon@noteflakes.com
|
|
@@ -690,14 +690,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
690
690
|
requirements:
|
|
691
691
|
- - ">="
|
|
692
692
|
- !ruby/object:Gem::Version
|
|
693
|
-
version: '3.
|
|
693
|
+
version: '3.5'
|
|
694
694
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
695
695
|
requirements:
|
|
696
696
|
- - ">="
|
|
697
697
|
- !ruby/object:Gem::Version
|
|
698
698
|
version: '0'
|
|
699
699
|
requirements: []
|
|
700
|
-
rubygems_version: 4.0.0
|
|
700
|
+
rubygems_version: 4.0.0
|
|
701
701
|
specification_version: 4
|
|
702
702
|
summary: A lean, mean io_uring machine
|
|
703
703
|
test_files: []
|