uringmachine 0.13 → 0.14
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 +4 -0
- data/ext/um/um.c +51 -40
- data/ext/um/um.h +5 -1
- data/ext/um/um_async_op.c +1 -2
- data/ext/um/um_class.c +11 -0
- data/ext/um/um_sync.c +2 -2
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +8 -7
- data/test/helper.rb +16 -0
- data/test/test_fiber.rb +3 -4
- data/test/test_um.rb +58 -15
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38a9b75f18075a31aa179cc63b67e7e80b75b3797a701e1b2164831f4c20c352
|
4
|
+
data.tar.gz: 50432253c8aca2713b7eeaf8ae69c72c1e4efece1c85285076cf91c97011a887
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7426118f51b6b3460d7ec46cc6e64e8a3aaa50e2552d2c44f718cfa79a9624310d9d68148f030be5a03582abf3fe520389e7a27fb814cff141c78f327f4f76a
|
7
|
+
data.tar.gz: a2e0ce93138435f99f84956ba82004fe06b4c7f530c37aa6585d998f2a4f6c448eac406ef0c7c602335bc776c5d40b543288f6e5cf16b1fe8bab1141fe7569c6
|
data/CHANGELOG.md
CHANGED
data/ext/um/um.c
CHANGED
@@ -252,20 +252,14 @@ inline VALUE um_await(struct um *machine) {
|
|
252
252
|
return raise_if_exception(v);
|
253
253
|
}
|
254
254
|
|
255
|
-
inline void um_prep_op(struct um *machine, struct um_op *op, enum op_kind kind) {
|
255
|
+
inline void um_prep_op(struct um *machine, struct um_op *op, enum op_kind kind, unsigned flags) {
|
256
256
|
memset(op, 0, sizeof(struct um_op));
|
257
257
|
op->kind = kind;
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
case OP_SLEEP_MULTISHOT:
|
264
|
-
op->flags |= OP_F_MULTISHOT;
|
265
|
-
default:
|
266
|
-
}
|
267
|
-
RB_OBJ_WRITE(machine->self, &op->fiber, rb_fiber_current());
|
268
|
-
op->value = Qnil;
|
258
|
+
op->flags = flags;
|
259
|
+
|
260
|
+
VALUE fiber = (flags & OP_F_FREE_ON_COMPLETE) ? Qnil : rb_fiber_current();
|
261
|
+
RB_OBJ_WRITE(machine->self, &op->fiber, fiber);
|
262
|
+
RB_OBJ_WRITE(machine->self, &op->value, Qnil);
|
269
263
|
}
|
270
264
|
|
271
265
|
inline void um_schedule(struct um *machine, VALUE fiber, VALUE value) {
|
@@ -307,7 +301,7 @@ VALUE um_timeout(struct um *machine, VALUE interval, VALUE class) {
|
|
307
301
|
if (!ID_new) ID_new = rb_intern("new");
|
308
302
|
|
309
303
|
struct um_op *op = um_op_alloc(machine);
|
310
|
-
um_prep_op(machine, op, OP_TIMEOUT);
|
304
|
+
um_prep_op(machine, op, OP_TIMEOUT, 0);
|
311
305
|
op->ts = um_double_to_timespec(NUM2DBL(interval));
|
312
306
|
RB_OBJ_WRITE(machine->self, &op->fiber, rb_fiber_current());
|
313
307
|
RB_OBJ_WRITE(machine->self, &op->value, rb_funcall(class, ID_new, 0));
|
@@ -325,7 +319,7 @@ VALUE um_timeout(struct um *machine, VALUE interval, VALUE class) {
|
|
325
319
|
|
326
320
|
VALUE um_sleep(struct um *machine, double duration) {
|
327
321
|
struct um_op op;
|
328
|
-
um_prep_op(machine, &op, OP_SLEEP);
|
322
|
+
um_prep_op(machine, &op, OP_SLEEP, 0);
|
329
323
|
op.ts = um_double_to_timespec(duration);
|
330
324
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
331
325
|
io_uring_prep_timeout(sqe, &op.ts, 0, 0);
|
@@ -344,7 +338,7 @@ VALUE um_sleep(struct um *machine, double duration) {
|
|
344
338
|
|
345
339
|
inline VALUE um_read(struct um *machine, int fd, VALUE buffer, int maxlen, int buffer_offset) {
|
346
340
|
struct um_op op;
|
347
|
-
um_prep_op(machine, &op, OP_READ);
|
341
|
+
um_prep_op(machine, &op, OP_READ, 0);
|
348
342
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
349
343
|
void *ptr = um_prepare_read_buffer(buffer, maxlen, buffer_offset);
|
350
344
|
io_uring_prep_read(sqe, fd, ptr, maxlen, -1);
|
@@ -363,7 +357,7 @@ inline VALUE um_read(struct um *machine, int fd, VALUE buffer, int maxlen, int b
|
|
363
357
|
|
364
358
|
inline size_t um_read_raw(struct um *machine, int fd, char *buffer, int maxlen) {
|
365
359
|
struct um_op op;
|
366
|
-
um_prep_op(machine, &op, OP_READ);
|
360
|
+
um_prep_op(machine, &op, OP_READ, 0);
|
367
361
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
368
362
|
io_uring_prep_read(sqe, fd, buffer, maxlen, -1);
|
369
363
|
|
@@ -379,7 +373,7 @@ inline size_t um_read_raw(struct um *machine, int fd, char *buffer, int maxlen)
|
|
379
373
|
|
380
374
|
VALUE um_write(struct um *machine, int fd, VALUE str, int len) {
|
381
375
|
struct um_op op;
|
382
|
-
um_prep_op(machine, &op, OP_WRITE);
|
376
|
+
um_prep_op(machine, &op, OP_WRITE, 0);
|
383
377
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
384
378
|
const int str_len = RSTRING_LEN(str);
|
385
379
|
if (len > str_len) len = str_len;
|
@@ -397,10 +391,7 @@ VALUE um_write(struct um *machine, int fd, VALUE str, int len) {
|
|
397
391
|
|
398
392
|
VALUE um_write_async(struct um *machine, int fd, VALUE str) {
|
399
393
|
struct um_op *op = um_op_alloc(machine);
|
400
|
-
|
401
|
-
op->kind = OP_WRITE_ASYNC;
|
402
|
-
op->flags = OP_F_FREE_ON_COMPLETE;
|
403
|
-
op->fiber = Qnil;
|
394
|
+
um_prep_op(machine, op, OP_WRITE_ASYNC, OP_F_FREE_ON_COMPLETE);
|
404
395
|
RB_OBJ_WRITE(machine->self, &op->value, str);
|
405
396
|
|
406
397
|
struct io_uring_sqe *sqe = um_get_sqe(machine, op);
|
@@ -410,7 +401,7 @@ VALUE um_write_async(struct um *machine, int fd, VALUE str) {
|
|
410
401
|
|
411
402
|
VALUE um_close(struct um *machine, int fd) {
|
412
403
|
struct um_op op;
|
413
|
-
um_prep_op(machine, &op, OP_CLOSE);
|
404
|
+
um_prep_op(machine, &op, OP_CLOSE, 0);
|
414
405
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
415
406
|
io_uring_prep_close(sqe, fd);
|
416
407
|
|
@@ -422,9 +413,19 @@ VALUE um_close(struct um *machine, int fd) {
|
|
422
413
|
return raise_if_exception(ret);
|
423
414
|
}
|
424
415
|
|
416
|
+
VALUE um_close_async(struct um *machine, int fd) {
|
417
|
+
struct um_op *op = um_op_alloc(machine);
|
418
|
+
um_prep_op(machine, op, OP_CLOSE_ASYNC, OP_F_FREE_ON_COMPLETE);
|
419
|
+
|
420
|
+
struct io_uring_sqe *sqe = um_get_sqe(machine, op);
|
421
|
+
io_uring_prep_close(sqe, fd);
|
422
|
+
|
423
|
+
return INT2NUM(fd);
|
424
|
+
}
|
425
|
+
|
425
426
|
VALUE um_accept(struct um *machine, int fd) {
|
426
427
|
struct um_op op;
|
427
|
-
um_prep_op(machine, &op, OP_ACCEPT);
|
428
|
+
um_prep_op(machine, &op, OP_ACCEPT, 0);
|
428
429
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
429
430
|
io_uring_prep_accept(sqe, fd, NULL, NULL, 0);
|
430
431
|
|
@@ -438,7 +439,7 @@ VALUE um_accept(struct um *machine, int fd) {
|
|
438
439
|
|
439
440
|
VALUE um_socket(struct um *machine, int domain, int type, int protocol, uint flags) {
|
440
441
|
struct um_op op;
|
441
|
-
um_prep_op(machine, &op, OP_SOCKET);
|
442
|
+
um_prep_op(machine, &op, OP_SOCKET, 0);
|
442
443
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
443
444
|
io_uring_prep_socket(sqe, domain, type, protocol, flags);
|
444
445
|
|
@@ -452,7 +453,7 @@ VALUE um_socket(struct um *machine, int domain, int type, int protocol, uint fla
|
|
452
453
|
|
453
454
|
VALUE um_connect(struct um *machine, int fd, const struct sockaddr *addr, socklen_t addrlen) {
|
454
455
|
struct um_op op;
|
455
|
-
um_prep_op(machine, &op, OP_CONNECT);
|
456
|
+
um_prep_op(machine, &op, OP_CONNECT, 0);
|
456
457
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
457
458
|
io_uring_prep_connect(sqe, fd, addr, addrlen);
|
458
459
|
|
@@ -466,7 +467,7 @@ VALUE um_connect(struct um *machine, int fd, const struct sockaddr *addr, sockle
|
|
466
467
|
|
467
468
|
VALUE um_send(struct um *machine, int fd, VALUE buffer, int len, int flags) {
|
468
469
|
struct um_op op;
|
469
|
-
um_prep_op(machine, &op, OP_SEND);
|
470
|
+
um_prep_op(machine, &op, OP_SEND, 0);
|
470
471
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
471
472
|
io_uring_prep_send(sqe, fd, RSTRING_PTR(buffer), len, flags);
|
472
473
|
|
@@ -481,7 +482,7 @@ VALUE um_send(struct um *machine, int fd, VALUE buffer, int len, int flags) {
|
|
481
482
|
|
482
483
|
VALUE um_recv(struct um *machine, int fd, VALUE buffer, int maxlen, int flags) {
|
483
484
|
struct um_op op;
|
484
|
-
um_prep_op(machine, &op, OP_RECV);
|
485
|
+
um_prep_op(machine, &op, OP_RECV, 0);
|
485
486
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
486
487
|
void *ptr = um_prepare_read_buffer(buffer, maxlen, 0);
|
487
488
|
io_uring_prep_recv(sqe, fd, ptr, maxlen, flags);
|
@@ -499,7 +500,7 @@ VALUE um_recv(struct um *machine, int fd, VALUE buffer, int maxlen, int flags) {
|
|
499
500
|
|
500
501
|
VALUE um_bind(struct um *machine, int fd, struct sockaddr *addr, socklen_t addrlen) {
|
501
502
|
struct um_op op;
|
502
|
-
um_prep_op(machine, &op, OP_BIND);
|
503
|
+
um_prep_op(machine, &op, OP_BIND, 0);
|
503
504
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
504
505
|
io_uring_prep_bind(sqe, fd, addr, addrlen);
|
505
506
|
|
@@ -513,7 +514,7 @@ VALUE um_bind(struct um *machine, int fd, struct sockaddr *addr, socklen_t addrl
|
|
513
514
|
|
514
515
|
VALUE um_listen(struct um *machine, int fd, int backlog) {
|
515
516
|
struct um_op op;
|
516
|
-
um_prep_op(machine, &op, OP_BIND);
|
517
|
+
um_prep_op(machine, &op, OP_BIND, 0);
|
517
518
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
518
519
|
io_uring_prep_listen(sqe, fd, backlog);
|
519
520
|
|
@@ -531,7 +532,7 @@ VALUE um_getsockopt(struct um *machine, int fd, int level, int opt) {
|
|
531
532
|
|
532
533
|
#ifdef HAVE_IO_URING_PREP_CMD_SOCK
|
533
534
|
struct um_op op;
|
534
|
-
um_prep_op(machine, &op, OP_GETSOCKOPT);
|
535
|
+
um_prep_op(machine, &op, OP_GETSOCKOPT, 0);
|
535
536
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
536
537
|
io_uring_prep_cmd_sock(sqe, SOCKET_URING_OP_GETSOCKOPT, fd, level, opt, &value, sizeof(value));
|
537
538
|
|
@@ -555,7 +556,7 @@ VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value) {
|
|
555
556
|
|
556
557
|
#ifdef HAVE_IO_URING_PREP_CMD_SOCK
|
557
558
|
struct um_op op;
|
558
|
-
um_prep_op(machine, &op, OP_SETSOCKOPT);
|
559
|
+
um_prep_op(machine, &op, OP_SETSOCKOPT, 0);
|
559
560
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
560
561
|
io_uring_prep_cmd_sock(sqe, SOCKET_URING_OP_SETSOCKOPT, fd, level, opt, &value, sizeof(value));
|
561
562
|
|
@@ -577,7 +578,7 @@ VALUE um_shutdown(struct um *machine, int fd, int how) {
|
|
577
578
|
VALUE ret = Qnil;
|
578
579
|
|
579
580
|
struct um_op op;
|
580
|
-
um_prep_op(machine, &op, OP_SHUTDOWN);
|
581
|
+
um_prep_op(machine, &op, OP_SHUTDOWN, 0);
|
581
582
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
582
583
|
io_uring_prep_shutdown(sqe, fd, how);
|
583
584
|
|
@@ -589,9 +590,19 @@ VALUE um_shutdown(struct um *machine, int fd, int how) {
|
|
589
590
|
return raise_if_exception(ret);
|
590
591
|
}
|
591
592
|
|
593
|
+
VALUE um_shutdown_async(struct um *machine, int fd, int how) {
|
594
|
+
struct um_op *op = um_op_alloc(machine);
|
595
|
+
um_prep_op(machine, op, OP_SHUTDOWN_ASYNC, OP_F_FREE_ON_COMPLETE);
|
596
|
+
|
597
|
+
struct io_uring_sqe *sqe = um_get_sqe(machine, op);
|
598
|
+
io_uring_prep_shutdown(sqe, fd, how);
|
599
|
+
|
600
|
+
return INT2NUM(fd);
|
601
|
+
}
|
602
|
+
|
592
603
|
VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode) {
|
593
604
|
struct um_op op;
|
594
|
-
um_prep_op(machine, &op, OP_OPEN);
|
605
|
+
um_prep_op(machine, &op, OP_OPEN, 0);
|
595
606
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
596
607
|
io_uring_prep_open(sqe, StringValueCStr(pathname), flags, mode);
|
597
608
|
|
@@ -605,7 +616,7 @@ VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode) {
|
|
605
616
|
|
606
617
|
VALUE um_waitpid(struct um *machine, int pid, int options) {
|
607
618
|
struct um_op op;
|
608
|
-
um_prep_op(machine, &op, OP_WAITPID);
|
619
|
+
um_prep_op(machine, &op, OP_WAITPID, 0);
|
609
620
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
610
621
|
|
611
622
|
siginfo_t infop;
|
@@ -646,7 +657,7 @@ VALUE statx_to_hash(struct statx *stat) {
|
|
646
657
|
|
647
658
|
VALUE um_statx(struct um *machine, int dirfd, VALUE path, int flags, unsigned int mask) {
|
648
659
|
struct um_op op;
|
649
|
-
um_prep_op(machine, &op, OP_STATX);
|
660
|
+
um_prep_op(machine, &op, OP_STATX, 0);
|
650
661
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
651
662
|
|
652
663
|
struct statx stat;
|
@@ -721,7 +732,7 @@ VALUE multishot_complete(VALUE arg) {
|
|
721
732
|
|
722
733
|
VALUE um_accept_each(struct um *machine, int fd) {
|
723
734
|
struct um_op op;
|
724
|
-
um_prep_op(machine, &op, OP_ACCEPT_MULTISHOT);
|
735
|
+
um_prep_op(machine, &op, OP_ACCEPT_MULTISHOT, OP_F_MULTISHOT);
|
725
736
|
|
726
737
|
struct op_ctx ctx = { .machine = machine, .op = &op, .fd = fd, .read_buf = NULL };
|
727
738
|
return rb_ensure(accept_each_start, (VALUE)&ctx, multishot_complete, (VALUE)&ctx);
|
@@ -734,7 +745,7 @@ int um_read_each_singleshot_loop(struct op_ctx *ctx) {
|
|
734
745
|
int total = 0;
|
735
746
|
|
736
747
|
while (1) {
|
737
|
-
um_prep_op(ctx->machine, ctx->op, OP_READ);
|
748
|
+
um_prep_op(ctx->machine, ctx->op, OP_READ, 0);
|
738
749
|
struct io_uring_sqe *sqe = um_get_sqe(ctx->machine, ctx->op);
|
739
750
|
io_uring_prep_read(sqe, ctx->fd, ctx->read_buf, ctx->read_maxlen, -1);
|
740
751
|
|
@@ -824,7 +835,7 @@ VALUE read_recv_each_start(VALUE arg) {
|
|
824
835
|
|
825
836
|
VALUE um_read_each(struct um *machine, int fd, int bgid) {
|
826
837
|
struct um_op op;
|
827
|
-
um_prep_op(machine, &op, OP_READ_MULTISHOT);
|
838
|
+
um_prep_op(machine, &op, OP_READ_MULTISHOT, OP_F_MULTISHOT);
|
828
839
|
|
829
840
|
struct op_ctx ctx = { .machine = machine, .op = &op, .fd = fd, .bgid = bgid, .read_buf = NULL };
|
830
841
|
return rb_ensure(read_recv_each_start, (VALUE)&ctx, multishot_complete, (VALUE)&ctx);
|
@@ -832,7 +843,7 @@ VALUE um_read_each(struct um *machine, int fd, int bgid) {
|
|
832
843
|
|
833
844
|
VALUE um_recv_each(struct um *machine, int fd, int bgid, int flags) {
|
834
845
|
struct um_op op;
|
835
|
-
um_prep_op(machine, &op, OP_RECV_MULTISHOT);
|
846
|
+
um_prep_op(machine, &op, OP_RECV_MULTISHOT, OP_F_MULTISHOT);
|
836
847
|
|
837
848
|
struct op_ctx ctx = { .machine = machine, .op = &op, .fd = fd, .bgid = bgid, .read_buf = NULL, .flags = flags };
|
838
849
|
return rb_ensure(read_recv_each_start, (VALUE)&ctx, multishot_complete, (VALUE)&ctx);
|
@@ -871,7 +882,7 @@ VALUE periodically_start(VALUE arg) {
|
|
871
882
|
|
872
883
|
VALUE um_periodically(struct um *machine, double interval) {
|
873
884
|
struct um_op op;
|
874
|
-
um_prep_op(machine, &op, OP_SLEEP_MULTISHOT);
|
885
|
+
um_prep_op(machine, &op, OP_SLEEP_MULTISHOT, OP_F_MULTISHOT);
|
875
886
|
op.ts = um_double_to_timespec(interval);
|
876
887
|
|
877
888
|
struct op_ctx ctx = { .machine = machine, .op = &op, .ts = op.ts, .read_buf = NULL };
|
data/ext/um/um.h
CHANGED
@@ -30,6 +30,7 @@ enum op_kind {
|
|
30
30
|
OP_WRITE,
|
31
31
|
OP_WRITE_ASYNC,
|
32
32
|
OP_CLOSE,
|
33
|
+
OP_CLOSE_ASYNC,
|
33
34
|
OP_STATX,
|
34
35
|
|
35
36
|
OP_ACCEPT,
|
@@ -42,6 +43,7 @@ enum op_kind {
|
|
42
43
|
OP_GETSOCKOPT,
|
43
44
|
OP_SETSOCKOPT,
|
44
45
|
OP_SHUTDOWN,
|
46
|
+
OP_SHUTDOWN_ASYNC,
|
45
47
|
|
46
48
|
OP_WAITPID,
|
47
49
|
|
@@ -202,7 +204,7 @@ VALUE um_raise_exception(VALUE v);
|
|
202
204
|
|
203
205
|
#define raise_if_exception(v) (um_value_is_exception_p(v) ? um_raise_exception(v) : v)
|
204
206
|
|
205
|
-
void um_prep_op(struct um *machine, struct um_op *op, enum op_kind kind);
|
207
|
+
void um_prep_op(struct um *machine, struct um_op *op, enum op_kind kind, unsigned flags);
|
206
208
|
void um_raise_on_error_result(int result);
|
207
209
|
void * um_prepare_read_buffer(VALUE buffer, unsigned len, int ofs);
|
208
210
|
void um_update_read_buffer(struct um *machine, VALUE buffer, int buffer_offset, __s32 result, __u32 flags);
|
@@ -229,6 +231,7 @@ size_t um_read_raw(struct um *machine, int fd, char *buffer, int maxlen);
|
|
229
231
|
VALUE um_read_each(struct um *machine, int fd, int bgid);
|
230
232
|
VALUE um_write(struct um *machine, int fd, VALUE str, int len);
|
231
233
|
VALUE um_close(struct um *machine, int fd);
|
234
|
+
VALUE um_close_async(struct um *machine, int fd);
|
232
235
|
VALUE um_open(struct um *machine, VALUE pathname, int flags, int mode);
|
233
236
|
VALUE um_waitpid(struct um *machine, int pid, int options);
|
234
237
|
VALUE um_statx(struct um *machine, int dirfd, VALUE path, int flags, unsigned int mask);
|
@@ -246,6 +249,7 @@ VALUE um_listen(struct um *machine, int fd, int backlog);
|
|
246
249
|
VALUE um_getsockopt(struct um *machine, int fd, int level, int opt);
|
247
250
|
VALUE um_setsockopt(struct um *machine, int fd, int level, int opt, int value);
|
248
251
|
VALUE um_shutdown(struct um *machine, int fd, int how);
|
252
|
+
VALUE um_shutdown_async(struct um *machine, int fd, int how);
|
249
253
|
|
250
254
|
void um_async_op_set(VALUE self, struct um *machine, struct um_op *op);
|
251
255
|
VALUE um_async_op_await(struct um_async_op *async_op);
|
data/ext/um/um_async_op.c
CHANGED
@@ -6,9 +6,8 @@ VALUE um_prep_timeout(struct um *machine, double interval) {
|
|
6
6
|
if (!ID_new) ID_new = rb_intern("new");
|
7
7
|
|
8
8
|
struct um_op *op = malloc(sizeof(struct um_op));
|
9
|
-
um_prep_op(machine, op, OP_TIMEOUT);
|
9
|
+
um_prep_op(machine, op, OP_TIMEOUT, OP_F_TRANSIENT | OP_F_ASYNC);
|
10
10
|
op->ts = um_double_to_timespec(interval);
|
11
|
-
op->flags = OP_F_TRANSIENT | OP_F_ASYNC;
|
12
11
|
|
13
12
|
VALUE obj = rb_funcall(cAsyncOp, rb_intern_const("new"), 0);
|
14
13
|
um_async_op_set(obj, machine, op);
|
data/ext/um/um_class.c
CHANGED
@@ -146,6 +146,11 @@ VALUE UM_close(VALUE self, VALUE fd) {
|
|
146
146
|
return um_close(machine, NUM2INT(fd));
|
147
147
|
}
|
148
148
|
|
149
|
+
VALUE UM_close_async(VALUE self, VALUE fd) {
|
150
|
+
struct um *machine = um_get_machine(self);
|
151
|
+
return um_close_async(machine, NUM2INT(fd));
|
152
|
+
}
|
153
|
+
|
149
154
|
VALUE UM_accept(VALUE self, VALUE fd) {
|
150
155
|
struct um *machine = um_get_machine(self);
|
151
156
|
return um_accept(machine, NUM2INT(fd));
|
@@ -164,7 +169,11 @@ VALUE UM_socket(VALUE self, VALUE domain, VALUE type, VALUE protocol, VALUE flag
|
|
164
169
|
VALUE UM_shutdown(VALUE self, VALUE fd, VALUE how) {
|
165
170
|
struct um *machine = um_get_machine(self);
|
166
171
|
return um_shutdown(machine, NUM2INT(fd), NUM2INT(how));
|
172
|
+
}
|
167
173
|
|
174
|
+
VALUE UM_shutdown_async(VALUE self, VALUE fd, VALUE how) {
|
175
|
+
struct um *machine = um_get_machine(self);
|
176
|
+
return um_shutdown_async(machine, NUM2INT(fd), NUM2INT(how));
|
168
177
|
}
|
169
178
|
|
170
179
|
VALUE UM_connect(VALUE self, VALUE fd, VALUE host, VALUE port) {
|
@@ -347,6 +356,7 @@ void Init_UM(void) {
|
|
347
356
|
rb_define_method(cUM, "yield", UM_yield, 0);
|
348
357
|
|
349
358
|
rb_define_method(cUM, "close", UM_close, 1);
|
359
|
+
rb_define_method(cUM, "close_async", UM_close_async, 1);
|
350
360
|
rb_define_method(cUM, "open", UM_open, 2);
|
351
361
|
rb_define_method(cUM, "read", UM_read, -1);
|
352
362
|
rb_define_method(cUM, "read_each", UM_read_each, 2);
|
@@ -370,6 +380,7 @@ void Init_UM(void) {
|
|
370
380
|
rb_define_method(cUM, "setsockopt", UM_setsockopt, 4);
|
371
381
|
rb_define_method(cUM, "socket", UM_socket, 4);
|
372
382
|
rb_define_method(cUM, "shutdown", UM_shutdown, 2);
|
383
|
+
rb_define_method(cUM, "shutdown_async", UM_shutdown_async, 2);
|
373
384
|
|
374
385
|
rb_define_method(cUM, "prep_timeout", UM_prep_timeout, 1);
|
375
386
|
|
data/ext/um/um_sync.c
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
void um_futex_wait(struct um *machine, uint32_t *futex, uint32_t expect) {
|
8
8
|
struct um_op op;
|
9
|
-
um_prep_op(machine, &op, OP_FUTEX_WAIT);
|
9
|
+
um_prep_op(machine, &op, OP_FUTEX_WAIT, 0);
|
10
10
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
11
11
|
io_uring_prep_futex_wait(
|
12
12
|
sqe, (uint32_t *)futex, expect, FUTEX_BITSET_MATCH_ANY,
|
@@ -27,7 +27,7 @@ void um_futex_wait(struct um *machine, uint32_t *futex, uint32_t expect) {
|
|
27
27
|
|
28
28
|
void um_futex_wake(struct um *machine, uint32_t *futex, uint32_t num_waiters) {
|
29
29
|
struct um_op op;
|
30
|
-
um_prep_op(machine, &op, OP_FUTEX_WAKE);
|
30
|
+
um_prep_op(machine, &op, OP_FUTEX_WAKE, 0);
|
31
31
|
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
32
32
|
// submit futex_wait
|
33
33
|
io_uring_prep_futex_wake(
|
data/lib/uringmachine/version.rb
CHANGED
data/lib/uringmachine.rb
CHANGED
@@ -35,14 +35,15 @@ class UringMachine
|
|
35
35
|
f.add_done_listener(queue)
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
38
|
+
if pending
|
39
|
+
while !pending.empty?
|
40
|
+
f = self.shift(queue)
|
41
|
+
pending.delete(f)
|
42
|
+
results[f] = f.result
|
43
|
+
end
|
44
44
|
end
|
45
|
-
results.values
|
45
|
+
values = results.values
|
46
|
+
fibers.size == 1 ? values.first : values
|
46
47
|
end
|
47
48
|
|
48
49
|
def resolve(hostname, type = :A)
|
data/test/helper.rb
CHANGED
@@ -74,4 +74,20 @@ class UMBaseTest < Minitest::Test
|
|
74
74
|
@@port += 1
|
75
75
|
end
|
76
76
|
end
|
77
|
+
|
78
|
+
def make_socket_pair
|
79
|
+
port = 10000 + rand(30000)
|
80
|
+
server_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
81
|
+
@machine.setsockopt(server_fd, UM::SOL_SOCKET, UM::SO_REUSEADDR, true)
|
82
|
+
@machine.bind(server_fd, '127.0.0.1', port)
|
83
|
+
@machine.listen(server_fd, UM::SOMAXCONN)
|
84
|
+
|
85
|
+
client_conn_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
86
|
+
@machine.connect(client_conn_fd, '127.0.0.1', port)
|
87
|
+
|
88
|
+
server_conn_fd = @machine.accept(server_fd)
|
89
|
+
|
90
|
+
@machine.close(server_fd)
|
91
|
+
[client_conn_fd, server_conn_fd]
|
92
|
+
end
|
77
93
|
end
|
data/test/test_fiber.rb
CHANGED
@@ -88,7 +88,7 @@ class FiberJoinTest < UMBaseTest
|
|
88
88
|
res = machine.join(f)
|
89
89
|
assert_equal 0, x
|
90
90
|
assert_equal 3, machine.shift(q)
|
91
|
-
assert_equal
|
91
|
+
assert_equal 42, res
|
92
92
|
end
|
93
93
|
|
94
94
|
def test_join_multiple
|
@@ -125,7 +125,7 @@ class FiberJoinTest < UMBaseTest
|
|
125
125
|
f = machine.shift(q)
|
126
126
|
assert_kind_of Fiber, f
|
127
127
|
res = machine.join(f)
|
128
|
-
assert_equal
|
128
|
+
assert_equal :foo, res
|
129
129
|
ensure
|
130
130
|
t2.join
|
131
131
|
end
|
@@ -135,8 +135,7 @@ class FiberJoinTest < UMBaseTest
|
|
135
135
|
raise "Foobar"
|
136
136
|
end
|
137
137
|
|
138
|
-
|
139
|
-
e = res.first
|
138
|
+
e = machine.join(f)
|
140
139
|
assert_kind_of RuntimeError, e
|
141
140
|
assert_equal 'Foobar', e.message
|
142
141
|
end
|
data/test/test_um.rb
CHANGED
@@ -25,6 +25,12 @@ class SpinTest < UMBaseTest
|
|
25
25
|
|
26
26
|
assert_equal :foo, x
|
27
27
|
end
|
28
|
+
|
29
|
+
def test_spin_with_unhandled_exception
|
30
|
+
f = machine.spin { raise 'foo' }
|
31
|
+
result = machine.join(f)
|
32
|
+
assert_kind_of RuntimeError, result
|
33
|
+
end
|
28
34
|
end
|
29
35
|
|
30
36
|
class SnoozeTest < UMBaseTest
|
@@ -271,7 +277,7 @@ class PeriodicallyTest < UMBaseTest
|
|
271
277
|
rescue Cancel
|
272
278
|
cancel = 1
|
273
279
|
end
|
274
|
-
|
280
|
+
5.times { machine.snooze }
|
275
281
|
assert_equal 0, machine.pending_count
|
276
282
|
t1 = monotonic_clock
|
277
283
|
assert_in_range 0.05..0.08, t1 - t0
|
@@ -569,25 +575,31 @@ class CloseTest < UMBaseTest
|
|
569
575
|
|
570
576
|
assert_raises(Errno::EBADF) { machine.close(w.fileno) }
|
571
577
|
end
|
572
|
-
end
|
573
578
|
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
client_conn_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
583
|
-
@machine.connect(client_conn_fd, '127.0.0.1', port)
|
579
|
+
def test_close_bad_fd
|
580
|
+
r, w = IO.pipe
|
581
|
+
machine.close(w.fileno)
|
582
|
+
|
583
|
+
assert_raises(Errno::EBADF) { machine.close(w.fileno) }
|
584
|
+
end
|
585
|
+
end
|
584
586
|
|
585
|
-
|
587
|
+
class CloseAsyncTest < UMBaseTest
|
588
|
+
def test_close_async
|
589
|
+
r, w = IO.pipe
|
590
|
+
machine.write(w.fileno, 'foo')
|
591
|
+
assert_equal 'foo', r.readpartial(3)
|
586
592
|
|
587
|
-
|
588
|
-
|
593
|
+
assert_equal 0, machine.pending_count
|
594
|
+
machine.close_async(w.fileno)
|
595
|
+
assert_equal 1, machine.pending_count
|
596
|
+
machine.snooze
|
597
|
+
assert_equal 0, machine.pending_count
|
598
|
+
assert_equal '', r.read
|
589
599
|
end
|
600
|
+
end
|
590
601
|
|
602
|
+
class ShutdownTest < UMBaseTest
|
591
603
|
def test_shutdown
|
592
604
|
c_fd, s_fd = make_socket_pair
|
593
605
|
res = @machine.send(c_fd, 'abc', 3, 0)
|
@@ -619,6 +631,37 @@ class ShutdownTest < UMBaseTest
|
|
619
631
|
end
|
620
632
|
end
|
621
633
|
|
634
|
+
class ShutdownAsyncTest < UMBaseTest
|
635
|
+
def test_shutdown_async
|
636
|
+
c_fd, s_fd = make_socket_pair
|
637
|
+
res = @machine.send(c_fd, 'abc', 3, 0)
|
638
|
+
assert_equal 3, res
|
639
|
+
|
640
|
+
buf = +''
|
641
|
+
res = @machine.recv(s_fd, buf, 256, 0)
|
642
|
+
assert_equal 3, res
|
643
|
+
assert_equal 'abc', buf
|
644
|
+
|
645
|
+
res = @machine.shutdown_async(c_fd, UM::SHUT_WR)
|
646
|
+
assert_equal c_fd, res
|
647
|
+
|
648
|
+
machine.sleep(0.01)
|
649
|
+
assert_raises(Errno::EPIPE) { @machine.send(c_fd, 'abc', 3, 0) }
|
650
|
+
|
651
|
+
res = @machine.shutdown_async(s_fd, UM::SHUT_RD)
|
652
|
+
assert_equal s_fd, res
|
653
|
+
|
654
|
+
res = @machine.recv(s_fd, buf, 256, 0)
|
655
|
+
assert_equal 0, res
|
656
|
+
|
657
|
+
res = @machine.shutdown_async(c_fd, UM::SHUT_RDWR)
|
658
|
+
assert_equal c_fd, res
|
659
|
+
ensure
|
660
|
+
@machine.close(c_fd)
|
661
|
+
@machine.close(s_fd)
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
622
665
|
class AcceptTest < UMBaseTest
|
623
666
|
def setup
|
624
667
|
super
|