uringmachine 0.4 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -1
  3. data/CHANGELOG.md +16 -0
  4. data/README.md +44 -1
  5. data/TODO.md +12 -3
  6. data/examples/bm_snooze.rb +89 -0
  7. data/examples/bm_sqlite.rb +89 -0
  8. data/examples/bm_write.rb +56 -0
  9. data/examples/dns_client.rb +12 -0
  10. data/examples/http_server.rb +42 -43
  11. data/examples/pg.rb +85 -0
  12. data/examples/server_client.rb +64 -0
  13. data/examples/snooze.rb +44 -0
  14. data/examples/stream.rb +85 -0
  15. data/examples/write_dev_null.rb +16 -0
  16. data/ext/um/extconf.rb +81 -14
  17. data/ext/um/um.c +468 -414
  18. data/ext/um/um.h +149 -40
  19. data/ext/um/um_async_op.c +40 -0
  20. data/ext/um/um_async_op_class.c +136 -0
  21. data/ext/um/um_buffer.c +49 -0
  22. data/ext/um/um_class.c +176 -44
  23. data/ext/um/um_const.c +174 -9
  24. data/ext/um/um_ext.c +8 -0
  25. data/ext/um/um_mutex_class.c +47 -0
  26. data/ext/um/um_op.c +89 -111
  27. data/ext/um/um_queue_class.c +58 -0
  28. data/ext/um/um_ssl.c +850 -0
  29. data/ext/um/um_ssl.h +22 -0
  30. data/ext/um/um_ssl_class.c +138 -0
  31. data/ext/um/um_sync.c +273 -0
  32. data/ext/um/um_utils.c +1 -1
  33. data/lib/uringmachine/dns_resolver.rb +84 -0
  34. data/lib/uringmachine/ssl/context_builder.rb +96 -0
  35. data/lib/uringmachine/ssl.rb +394 -0
  36. data/lib/uringmachine/version.rb +1 -1
  37. data/lib/uringmachine.rb +27 -3
  38. data/supressions/ruby.supp +71 -0
  39. data/test/helper.rb +6 -0
  40. data/test/test_async_op.rb +119 -0
  41. data/test/test_ssl.rb +155 -0
  42. data/test/test_um.rb +464 -47
  43. data/uringmachine.gemspec +3 -2
  44. data/vendor/liburing/.gitignore +5 -0
  45. data/vendor/liburing/CHANGELOG +1 -0
  46. data/vendor/liburing/configure +32 -0
  47. data/vendor/liburing/examples/Makefile +1 -0
  48. data/vendor/liburing/examples/reg-wait.c +159 -0
  49. data/vendor/liburing/liburing.spec +1 -1
  50. data/vendor/liburing/src/include/liburing/io_uring.h +48 -2
  51. data/vendor/liburing/src/include/liburing.h +28 -2
  52. data/vendor/liburing/src/int_flags.h +10 -3
  53. data/vendor/liburing/src/liburing-ffi.map +13 -2
  54. data/vendor/liburing/src/liburing.map +9 -0
  55. data/vendor/liburing/src/queue.c +25 -16
  56. data/vendor/liburing/src/register.c +73 -4
  57. data/vendor/liburing/src/setup.c +46 -18
  58. data/vendor/liburing/src/setup.h +6 -0
  59. data/vendor/liburing/test/Makefile +7 -0
  60. data/vendor/liburing/test/cmd-discard.c +427 -0
  61. data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
  62. data/vendor/liburing/test/file-exit-unreg.c +48 -0
  63. data/vendor/liburing/test/io_uring_passthrough.c +2 -0
  64. data/vendor/liburing/test/io_uring_register.c +13 -2
  65. data/vendor/liburing/test/napi-test.c +1 -1
  66. data/vendor/liburing/test/no-mmap-inval.c +1 -1
  67. data/vendor/liburing/test/read-mshot-empty.c +2 -0
  68. data/vendor/liburing/test/read-mshot-stdin.c +121 -0
  69. data/vendor/liburing/test/read-mshot.c +6 -0
  70. data/vendor/liburing/test/recvsend_bundle.c +2 -2
  71. data/vendor/liburing/test/reg-fd-only.c +1 -1
  72. data/vendor/liburing/test/reg-wait.c +251 -0
  73. data/vendor/liburing/test/regbuf-clone.c +458 -0
  74. data/vendor/liburing/test/resize-rings.c +643 -0
  75. data/vendor/liburing/test/rsrc_tags.c +1 -1
  76. data/vendor/liburing/test/sqpoll-sleep.c +39 -8
  77. data/vendor/liburing/test/sqwait.c +136 -0
  78. data/vendor/liburing/test/sync-cancel.c +8 -1
  79. data/vendor/liburing/test/timeout.c +13 -8
  80. metadata +52 -8
  81. data/examples/http_server_multishot.rb +0 -57
  82. data/examples/http_server_simpler.rb +0 -34
data/ext/um/um_op.c CHANGED
@@ -1,148 +1,126 @@
1
1
  #include "um.h"
2
2
 
3
- inline struct um_result_entry *um_result_checkout(struct um *machine) {
4
- if (machine->result_freelist) {
5
- struct um_result_entry *entry = machine->result_freelist;
6
- machine->result_freelist = entry->next;
7
- return entry;
8
- }
9
-
10
- struct um_result_entry *entry = malloc(sizeof(struct um_result_entry));
11
- return entry;
12
- }
13
-
14
- inline void um_result_checkin(struct um *machine, struct um_result_entry *entry) {
15
- entry->next = machine->result_freelist;
16
- machine->result_freelist = entry;
3
+ inline void um_op_clear(struct um *machine, struct um_op *op) {
4
+ memset(op, 0, sizeof(struct um_op));
5
+ op->fiber = Qnil;
6
+ op->value = Qnil;
7
+ op->async_op = Qnil;
17
8
  }
18
9
 
19
- inline void um_op_result_cleanup(struct um *machine, struct um_op *op) {
20
- struct um_result_entry *entry = op->results_head;
21
- while (entry) {
22
- struct um_result_entry *next = entry->next;
23
- um_result_checkin(machine, entry);
24
- entry = next;
10
+ inline void um_op_transient_add(struct um *machine, struct um_op *op) {
11
+ if (machine->transient_head) {
12
+ op->next = machine->transient_head;
13
+ machine->transient_head->prev = op;
25
14
  }
26
- op->results_head = op->results_tail = NULL;
15
+ machine->transient_head = op;
27
16
  }
28
17
 
29
- inline void um_op_result_push(struct um *machine, struct um_op *op, __s32 result, __u32 flags) {
30
- struct um_result_entry *entry = um_result_checkout(machine);
31
- entry->next = 0;
32
- entry->result = result;
33
- entry->flags = flags;
34
- if (op->results_tail) {
35
- op->results_tail->next = entry;
36
- op->results_tail = entry;
37
- }
38
- else {
39
- op->results_head = op->results_tail = entry;
40
- }
41
- }
18
+ inline void um_op_transient_remove(struct um *machine, struct um_op *op) {
19
+ if (op->prev)
20
+ op->prev->next = op->next;
21
+ if (op->next)
22
+ op->next->prev = op->prev;
42
23
 
43
- inline int um_op_result_shift(struct um *machine, struct um_op *op, __s32 *result, __u32 *flags) {
44
- if (!op->results_head) return 0;
45
-
46
- struct um_result_entry *entry = op->results_head;
47
- *result = entry->result;
48
- *flags = entry->flags;
49
- op->results_head = entry->next;
50
- if (!op->results_head)
51
- op->results_tail = NULL;
52
- um_result_checkin(machine, entry);
53
- return 1;
24
+ if (machine->transient_head == op)
25
+ machine->transient_head = op->next;
54
26
  }
55
27
 
56
- inline void um_op_clear(struct um_op *op) {
57
- memset(op, 0, sizeof(struct um_op));
58
- op->fiber = op->resume_value = Qnil;
28
+ inline void um_runqueue_push(struct um *machine, struct um_op *op) {
29
+ if (machine->runqueue_tail) {
30
+ op->prev = machine->runqueue_tail;
31
+ machine->runqueue_tail->next = op;
32
+ machine->runqueue_tail = op;
33
+ }
34
+ else
35
+ machine->runqueue_head = machine->runqueue_tail = op;
36
+ op->next = NULL;
59
37
  }
60
38
 
61
- inline struct um_op *um_op_checkout(struct um *machine) {
62
- machine->pending_count++;
63
-
64
- struct um_op *op = machine->op_freelist;
65
- if (op)
66
- machine->op_freelist = op->next;
67
- else
68
- op = malloc(sizeof(struct um_op));
39
+ inline struct um_op *um_runqueue_shift(struct um *machine) {
40
+ struct um_op *op = machine->runqueue_head;
41
+ if (!op) return NULL;
69
42
 
70
- um_op_clear(op);
43
+ machine->runqueue_head = op->next;
44
+ if (!machine->runqueue_head)
45
+ machine->runqueue_tail = NULL;
71
46
  return op;
72
47
  }
73
48
 
74
- inline void um_op_checkin(struct um *machine, struct um_op *op) {
75
- machine->pending_count--;
76
-
77
- um_op_result_cleanup(machine, op);
78
- op->next = machine->op_freelist;
79
- machine->op_freelist = op;
49
+ inline void um_op_list_mark(struct um *machine, struct um_op *head) {
50
+ while (head) {
51
+ struct um_op *next = head->next;
52
+ rb_gc_mark_movable(head->fiber);
53
+ rb_gc_mark_movable(head->value);
54
+ rb_gc_mark_movable(head->async_op);
55
+ head = next;
56
+ }
80
57
  }
81
58
 
82
- inline struct um_op *um_runqueue_find_by_fiber(struct um *machine, VALUE fiber) {
83
- struct um_op *op = machine->runqueue_head;
84
- while (op) {
85
- if (op->fiber == fiber) return op;
86
-
87
- op = op->next;
59
+ inline void um_op_list_compact(struct um *machine, struct um_op *head) {
60
+ while (head) {
61
+ struct um_op *next = head->next;
62
+ head->fiber = rb_gc_location(head->fiber);
63
+ head->value = rb_gc_location(head->value);
64
+ head->async_op = rb_gc_location(head->async_op);
65
+ head = next;
88
66
  }
89
- return NULL;
90
67
  }
91
68
 
92
- inline void um_runqueue_push(struct um *machine, struct um_op *op) {
93
- if (machine->runqueue_tail) {
94
- op->prev = machine->runqueue_tail;
95
- machine->runqueue_tail->next = op;
96
- machine->runqueue_tail = op;
97
- }
98
- else {
99
- op->prev = NULL;
100
- machine->runqueue_head = machine->runqueue_tail = op;
69
+ inline struct um_op_result *multishot_result_alloc(struct um *machine) {
70
+ if (machine->result_freelist) {
71
+ struct um_op_result *result = machine->result_freelist;
72
+ machine->result_freelist = result->next;
73
+ return result;
101
74
  }
102
- op->next = NULL;
75
+ return malloc(sizeof(struct um_op_result));
103
76
  }
104
77
 
105
- inline void um_runqueue_unshift(struct um *machine, struct um_op *op) {
106
- if (machine->runqueue_head) {
107
- op->next = machine->runqueue_head;
108
- machine->runqueue_head->prev = op;
109
- machine->runqueue_head = op;
78
+ inline void multishot_result_free(struct um *machine, struct um_op_result *result) {
79
+ result->next = machine->result_freelist;
80
+ machine->result_freelist = result;
81
+ }
82
+
83
+ inline void um_op_multishot_results_push(struct um *machine, struct um_op *op, __s32 res, __u32 flags) {
84
+ if (!op->multishot_result_count) {
85
+ op->result.res = res;
86
+ op->result.flags = flags;
87
+ op->result.next = NULL;
88
+ op->multishot_result_tail = &op->result;
110
89
  }
111
90
  else {
112
- op->next = NULL;
113
- machine->runqueue_head = machine->runqueue_tail = op;
91
+ struct um_op_result *result = multishot_result_alloc(machine);
92
+ result->res = res;
93
+ result->flags = flags;
94
+ result->next = NULL;
95
+ op->multishot_result_tail->next = result;
96
+ op->multishot_result_tail = result;
114
97
  }
115
- op->prev = NULL;
98
+ op->multishot_result_count++;
116
99
  }
117
100
 
118
- inline struct um_op *um_runqueue_shift(struct um *machine) {
119
- struct um_op *op = machine->runqueue_head;
120
- if (!op) return NULL;
101
+ inline void um_op_multishot_results_clear(struct um *machine, struct um_op *op) {
102
+ if (op->multishot_result_count < 1) return;
121
103
 
122
- op->prev = NULL;
123
- if (!op->next) {
124
- machine->runqueue_head = machine->runqueue_tail = NULL;
104
+ struct um_op_result *result = op->result.next;
105
+ while (result) {
106
+ struct um_op_result *next = result->next;
107
+ multishot_result_free(machine, result);
108
+ result = next;
125
109
  }
126
- else {
127
- machine->runqueue_head = op->next;
128
- op->next = NULL;
129
- }
130
- return op;
110
+ op->multishot_result_tail = NULL;
111
+ op->multishot_result_count = 0;
131
112
  }
132
113
 
133
- inline void um_free_op_linked_list(struct um *machine, struct um_op *op) {
134
- while (op) {
135
- struct um_op *next = op->next;
136
- um_op_result_cleanup(machine, op);
137
- free(op);
138
- op = next;
114
+ inline struct um_op *um_op_alloc(struct um *machine) {
115
+ if (machine->op_freelist) {
116
+ struct um_op *op = machine->op_freelist;
117
+ machine->op_freelist = op->next;
118
+ return op;
139
119
  }
120
+ return malloc(sizeof(struct um_op));
140
121
  }
141
122
 
142
- inline void um_free_result_linked_list(struct um *machine, struct um_result_entry *entry) {
143
- while (entry) {
144
- struct um_result_entry *next = entry->next;
145
- free(entry);
146
- entry = next;
147
- }
123
+ inline void um_op_free(struct um *machine, struct um_op *op) {
124
+ op->next = machine->op_freelist;
125
+ machine->op_freelist = op;
148
126
  }
@@ -0,0 +1,58 @@
1
+ #include "um.h"
2
+ #include <stdlib.h>
3
+
4
+ VALUE cQueue;
5
+
6
+ static void Queue_mark(void *ptr) {
7
+ struct um_queue *queue = ptr;
8
+ um_queue_mark(queue);
9
+ }
10
+
11
+ static void Queue_compact(void *ptr) {
12
+ struct um_queue *queue = ptr;
13
+ um_queue_compact(queue);
14
+ }
15
+
16
+ static void Queue_free(void *ptr) {
17
+ struct um_queue *queue = ptr;
18
+ um_queue_free(queue);
19
+ }
20
+
21
+ static size_t Queue_size(const void *ptr) {
22
+ return sizeof(struct um_queue);
23
+ }
24
+
25
+ static const rb_data_type_t Queue_type = {
26
+ "UringMachineQueue",
27
+ {Queue_mark, Queue_free, Queue_size, Queue_compact},
28
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
29
+ };
30
+
31
+ static VALUE Queue_allocate(VALUE klass) {
32
+ struct um_queue *queue = malloc(sizeof(struct um_queue));
33
+ return TypedData_Wrap_Struct(klass, &Queue_type, queue);
34
+ }
35
+
36
+ inline struct um_queue *Queue_data(VALUE self) {
37
+ return RTYPEDDATA_DATA(self);
38
+ }
39
+
40
+ VALUE Queue_initialize(VALUE self) {
41
+ struct um_queue *queue = Queue_data(self);
42
+ RB_OBJ_WRITE(self, &queue->self, self);
43
+ um_queue_init(queue);
44
+ return self;
45
+ }
46
+
47
+ VALUE Queue_count(VALUE self) {
48
+ struct um_queue *queue = Queue_data(self);
49
+ return UINT2NUM(queue->count);
50
+ }
51
+
52
+ void Init_Queue(void) {
53
+ cQueue = rb_define_class_under(cUM, "Queue", rb_cObject);
54
+ rb_define_alloc_func(cQueue, Queue_allocate);
55
+
56
+ rb_define_method(cQueue, "initialize", Queue_initialize, 0);
57
+ rb_define_method(cQueue, "count", Queue_count, 0);
58
+ }