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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bce8525371c9f0aa2b279b815d04456573319b3eddaae14b79ddbf20ece1189f
4
- data.tar.gz: dc1e70ca4101d607f2c04df639dabc917c379e3765a12c5440682a72cbb24316
3
+ metadata.gz: 38a9b75f18075a31aa179cc63b67e7e80b75b3797a701e1b2164831f4c20c352
4
+ data.tar.gz: 50432253c8aca2713b7eeaf8ae69c72c1e4efece1c85285076cf91c97011a887
5
5
  SHA512:
6
- metadata.gz: 258605dfe54482f5330a7795e18efa3397692b0a306cf7fd1ad6a2408fe8c7e098abca78d66baaddd78faac74aae6beeda9fe6a3d2e39ab4e196b585810bc212
7
- data.tar.gz: 6110908bf2c3d8a404f015429835dfb585ae711f14457b785d7e298f6caf2449341ca62ab3fa560054f51c9de6031195e8ead20afabace47cfe24cdf9fd6ae48
6
+ metadata.gz: c7426118f51b6b3460d7ec46cc6e64e8a3aaa50e2552d2c44f718cfa79a9624310d9d68148f030be5a03582abf3fe520389e7a27fb814cff141c78f327f4f76a
7
+ data.tar.gz: a2e0ce93138435f99f84956ba82004fe06b4c7f530c37aa6585d998f2a4f6c448eac406ef0c7c602335bc776c5d40b543288f6e5cf16b1fe8bab1141fe7569c6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 2025-06-09 Version 0.14
2
+
3
+ - Add `#close_async`, `#shutdown_async`
4
+
1
5
  # 2025-06-07 Version 0.13
2
6
 
3
7
  - Add `#write_async`
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
- switch (kind) {
259
- case OP_ACCEPT_MULTISHOT:
260
- case OP_READ_MULTISHOT:
261
- case OP_RECV_MULTISHOT:
262
- case OP_TIMEOUT_MULTISHOT:
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
- memset(op, 0, sizeof(struct um_op));
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(
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class UringMachine
4
- VERSION = '0.13'
4
+ VERSION = '0.14'
5
5
  end
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
- return results.values if !pending
39
-
40
- while !pending.empty?
41
- f = self.shift(queue)
42
- pending.delete(f)
43
- results[f] = f.result
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 [42], res
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 [:foo], res
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
- res = machine.join(f)
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
- 2.times { machine.snooze }
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
- class ShutdownTest < UMBaseTest
575
- def make_socket_pair
576
- port = 10000 + rand(30000)
577
- server_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
578
- @machine.setsockopt(server_fd, UM::SOL_SOCKET, UM::SO_REUSEADDR, true)
579
- @machine.bind(server_fd, '127.0.0.1', port)
580
- @machine.listen(server_fd, UM::SOMAXCONN)
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
- server_conn_fd = @machine.accept(server_fd)
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
- @machine.close(server_fd)
588
- [client_conn_fd, server_conn_fd]
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
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.13'
4
+ version: '0.14'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner