uringmachine 0.31.0 → 0.33.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/CHANGELOG.md +9 -0
- data/README.md +36 -37
- data/TODO.md +40 -59
- data/benchmark/bm_io_pipe.rb +2 -2
- data/benchmark/common.rb +16 -16
- data/benchmark/gets.rb +7 -7
- data/benchmark/gets_concurrent.rb +12 -12
- data/benchmark/http_parse.rb +11 -11
- data/benchmark/http_server_accept_queue.rb +7 -7
- data/benchmark/http_server_multi_accept.rb +7 -7
- data/benchmark/http_server_multi_ractor.rb +7 -7
- data/benchmark/http_server_single_thread.rb +8 -8
- data/benchmark/openssl.rb +4 -4
- data/docs/um_api.md +4 -9
- data/examples/fiber_concurrency_io.rb +1 -1
- data/examples/fiber_concurrency_um.rb +16 -0
- data/examples/io_uring_simple.c +13 -4
- data/examples/pg.rb +2 -2
- data/examples/um_cancellation.rb +20 -0
- data/examples/um_fiber_scheduler.rb +10 -0
- data/examples/um_io.rb +19 -0
- data/examples/um_mo.c +32 -0
- data/examples/um_multishot.rb +15 -0
- data/examples/um_ssl.rb +11 -0
- data/ext/um/um.c +21 -76
- data/ext/um/um.h +22 -41
- data/ext/um/um_class.c +11 -65
- data/ext/um/um_ext.c +2 -4
- data/ext/um/{um_connection.c → um_io.c} +209 -210
- data/ext/um/{um_connection_class.c → um_io_class.c} +102 -102
- data/ext/um/um_op.c +0 -1
- data/ext/um/um_utils.c +0 -86
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +12 -12
- data/test/{test_connection.rb → test_io.rb} +63 -63
- data/test/test_um.rb +17 -95
- metadata +13 -6
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
#include "um.h"
|
|
2
2
|
|
|
3
|
-
VALUE
|
|
4
|
-
VALUE
|
|
3
|
+
VALUE cIO;
|
|
4
|
+
VALUE eIORESPError;
|
|
5
5
|
|
|
6
6
|
VALUE SYM_fd;
|
|
7
7
|
VALUE SYM_socket;
|
|
8
8
|
VALUE SYM_ssl;
|
|
9
9
|
|
|
10
|
-
inline int
|
|
10
|
+
inline int io_has_target_obj_p(struct um_io *conn) {
|
|
11
11
|
switch (conn->mode) {
|
|
12
|
-
case
|
|
13
|
-
case
|
|
14
|
-
case
|
|
12
|
+
case IO_SSL:
|
|
13
|
+
case IO_STRING:
|
|
14
|
+
case IO_IO_BUFFER:
|
|
15
15
|
return true;
|
|
16
16
|
default:
|
|
17
17
|
return false;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
inline void
|
|
21
|
+
inline void io_mark_segments(struct um_io *conn) {
|
|
22
22
|
struct um_segment *curr = conn->head;
|
|
23
23
|
while (curr) {
|
|
24
24
|
// rb_gc_mark_movable(curr->obj);
|
|
@@ -26,7 +26,7 @@ inline void connection_mark_segments(struct um_connection *conn) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
inline void
|
|
29
|
+
inline void io_compact_segments(struct um_io *conn) {
|
|
30
30
|
struct um_segment *curr = conn->head;
|
|
31
31
|
while (curr) {
|
|
32
32
|
// curr->obj = rb_gc_location(curr->obj);
|
|
@@ -34,63 +34,63 @@ inline void connection_compact_segments(struct um_connection *conn) {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
static void
|
|
38
|
-
struct
|
|
37
|
+
static void IO_mark(void *ptr) {
|
|
38
|
+
struct um_io *conn = ptr;
|
|
39
39
|
rb_gc_mark_movable(conn->self);
|
|
40
40
|
rb_gc_mark_movable(conn->machine->self);
|
|
41
41
|
|
|
42
|
-
if (
|
|
42
|
+
if (io_has_target_obj_p(conn)) {
|
|
43
43
|
rb_gc_mark_movable(conn->target);
|
|
44
|
-
|
|
44
|
+
io_mark_segments(conn);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
static void
|
|
49
|
-
struct
|
|
48
|
+
static void IO_compact(void *ptr) {
|
|
49
|
+
struct um_io *conn = ptr;
|
|
50
50
|
conn->self = rb_gc_location(conn->self);
|
|
51
51
|
|
|
52
|
-
if (
|
|
52
|
+
if (io_has_target_obj_p(conn)) {
|
|
53
53
|
conn->target = rb_gc_location(conn->target);
|
|
54
|
-
|
|
54
|
+
io_compact_segments(conn);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
static void
|
|
59
|
-
struct
|
|
60
|
-
|
|
58
|
+
static void IO_free(void *ptr) {
|
|
59
|
+
struct um_io *conn = ptr;
|
|
60
|
+
io_clear(conn);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
static const rb_data_type_t
|
|
64
|
-
.wrap_struct_name = "UringMachine::
|
|
63
|
+
static const rb_data_type_t IO_type = {
|
|
64
|
+
.wrap_struct_name = "UringMachine::IO",
|
|
65
65
|
.function = {
|
|
66
|
-
.dmark =
|
|
67
|
-
.dfree =
|
|
66
|
+
.dmark = IO_mark,
|
|
67
|
+
.dfree = IO_free,
|
|
68
68
|
.dsize = NULL,
|
|
69
|
-
.dcompact =
|
|
69
|
+
.dcompact = IO_compact
|
|
70
70
|
},
|
|
71
71
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
-
static VALUE
|
|
75
|
-
struct
|
|
76
|
-
VALUE self = TypedData_Make_Struct(klass, struct
|
|
74
|
+
static VALUE IO_allocate(VALUE klass) {
|
|
75
|
+
struct um_io *conn;
|
|
76
|
+
VALUE self = TypedData_Make_Struct(klass, struct um_io, &IO_type, conn);
|
|
77
77
|
return self;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
static inline struct
|
|
81
|
-
struct
|
|
82
|
-
TypedData_Get_Struct(self, struct
|
|
80
|
+
static inline struct um_io *um_get_io(VALUE self) {
|
|
81
|
+
struct um_io *conn;
|
|
82
|
+
TypedData_Get_Struct(self, struct um_io, &IO_type, conn);
|
|
83
83
|
return conn;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
static inline void
|
|
86
|
+
static inline void io_set_target(struct um_io *conn, VALUE target, enum um_io_mode mode) {
|
|
87
87
|
conn->mode = mode;
|
|
88
88
|
switch (mode) {
|
|
89
|
-
case
|
|
90
|
-
case
|
|
89
|
+
case IO_FD:
|
|
90
|
+
case IO_SOCKET:
|
|
91
91
|
conn->fd = NUM2INT(target);
|
|
92
92
|
return;
|
|
93
|
-
case
|
|
93
|
+
case IO_SSL:
|
|
94
94
|
conn->target = target;
|
|
95
95
|
um_ssl_set_bio(conn->machine, target);
|
|
96
96
|
return;
|
|
@@ -99,20 +99,20 @@ static inline void connection_set_target(struct um_connection *conn, VALUE targe
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
static inline void
|
|
102
|
+
static inline void io_setup(struct um_io *conn, VALUE target, VALUE mode) {
|
|
103
103
|
conn->working_buffer = NULL;
|
|
104
104
|
if (NIL_P(mode)) {
|
|
105
105
|
if (TYPE(target) == T_DATA)
|
|
106
|
-
|
|
106
|
+
io_set_target(conn, target, IO_SSL);
|
|
107
107
|
else
|
|
108
|
-
|
|
108
|
+
io_set_target(conn, target, IO_FD);
|
|
109
109
|
}
|
|
110
110
|
else if (mode == SYM_fd)
|
|
111
|
-
|
|
111
|
+
io_set_target(conn, target, IO_FD);
|
|
112
112
|
else if (mode == SYM_socket)
|
|
113
|
-
|
|
113
|
+
io_set_target(conn, target, IO_SOCKET);
|
|
114
114
|
else if (mode == SYM_ssl)
|
|
115
|
-
|
|
115
|
+
io_set_target(conn, target, IO_SSL);
|
|
116
116
|
else
|
|
117
117
|
rb_raise(eUMError, "Invalid connection mode");
|
|
118
118
|
}
|
|
@@ -131,18 +131,18 @@ static inline void connection_setup(struct um_connection *conn, VALUE target, VA
|
|
|
131
131
|
* @param mode [Symbol] optional connection mode: :fd, :socket, :ssl
|
|
132
132
|
* @return [void]
|
|
133
133
|
*/
|
|
134
|
-
VALUE
|
|
134
|
+
VALUE IO_initialize(int argc, VALUE *argv, VALUE self) {
|
|
135
135
|
VALUE machine;
|
|
136
136
|
VALUE target;
|
|
137
137
|
VALUE mode;
|
|
138
138
|
rb_scan_args(argc, argv, "21", &machine, &target, &mode);
|
|
139
139
|
|
|
140
|
-
struct
|
|
141
|
-
memset(conn, 0, sizeof(struct
|
|
140
|
+
struct um_io *conn = um_get_io(self);
|
|
141
|
+
memset(conn, 0, sizeof(struct um_io));
|
|
142
142
|
|
|
143
143
|
RB_OBJ_WRITE(self, &conn->self, self);
|
|
144
144
|
conn->machine = um_get_machine(machine);
|
|
145
|
-
|
|
145
|
+
io_setup(conn, target, mode);
|
|
146
146
|
|
|
147
147
|
return self;
|
|
148
148
|
}
|
|
@@ -154,12 +154,12 @@ VALUE Connection_initialize(int argc, VALUE *argv, VALUE self) {
|
|
|
154
154
|
*
|
|
155
155
|
* @return [Symbol] connection mode
|
|
156
156
|
*/
|
|
157
|
-
VALUE
|
|
158
|
-
struct
|
|
157
|
+
VALUE IO_mode(VALUE self) {
|
|
158
|
+
struct um_io *conn = um_get_io(self);
|
|
159
159
|
switch (conn->mode) {
|
|
160
|
-
case
|
|
161
|
-
case
|
|
162
|
-
case
|
|
160
|
+
case IO_FD: return SYM_fd;
|
|
161
|
+
case IO_SOCKET: return SYM_socket;
|
|
162
|
+
case IO_SSL: return SYM_ssl;
|
|
163
163
|
default: return Qnil;
|
|
164
164
|
}
|
|
165
165
|
return Qnil;
|
|
@@ -175,9 +175,9 @@ VALUE Connection_mode(VALUE self) {
|
|
|
175
175
|
* @param limit [integer] maximum line length (0 means no limit)
|
|
176
176
|
* @return [String, nil] read data or nil
|
|
177
177
|
*/
|
|
178
|
-
VALUE
|
|
179
|
-
struct
|
|
180
|
-
return
|
|
178
|
+
VALUE IO_read_line(VALUE self, VALUE limit) {
|
|
179
|
+
struct um_io *conn = um_get_io(self);
|
|
180
|
+
return io_read_line(conn, Qnil, NUM2ULONG(limit));
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
/* call-seq:
|
|
@@ -190,9 +190,9 @@ VALUE Connection_read_line(VALUE self, VALUE limit) {
|
|
|
190
190
|
* @param len [integer] number of bytes to read
|
|
191
191
|
* @return [String, nil] read data or nil
|
|
192
192
|
*/
|
|
193
|
-
VALUE
|
|
194
|
-
struct
|
|
195
|
-
return
|
|
193
|
+
VALUE IO_read(VALUE self, VALUE len) {
|
|
194
|
+
struct um_io *conn = um_get_io(self);
|
|
195
|
+
return io_read(conn, Qnil, NUM2LONG(len), 0, false);
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
/* call-seq:
|
|
@@ -210,9 +210,9 @@ VALUE Connection_read(VALUE self, VALUE len) {
|
|
|
210
210
|
* @param delim [String] delimiter (single byte) @param limit [integer] maximum
|
|
211
211
|
* line length (0 means no limit) @return [String, nil] read data or nil
|
|
212
212
|
*/
|
|
213
|
-
VALUE
|
|
214
|
-
struct
|
|
215
|
-
return
|
|
213
|
+
VALUE IO_read_to_delim(VALUE self, VALUE delim, VALUE limit) {
|
|
214
|
+
struct um_io *conn = um_get_io(self);
|
|
215
|
+
return io_read_to_delim(conn, Qnil, delim, NUM2LONG(limit));
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
/* call-seq:
|
|
@@ -223,9 +223,9 @@ VALUE Connection_read_to_delim(VALUE self, VALUE delim, VALUE limit) {
|
|
|
223
223
|
* @param len [integer] number of bytes to skip
|
|
224
224
|
* @return [Integer] len
|
|
225
225
|
*/
|
|
226
|
-
VALUE
|
|
227
|
-
struct
|
|
228
|
-
|
|
226
|
+
VALUE IO_skip(VALUE self, VALUE len) {
|
|
227
|
+
struct um_io *conn = um_get_io(self);
|
|
228
|
+
io_skip(conn, NUM2LONG(len), true);
|
|
229
229
|
return len;
|
|
230
230
|
}
|
|
231
231
|
|
|
@@ -234,11 +234,11 @@ VALUE Connection_skip(VALUE self, VALUE len) {
|
|
|
234
234
|
*
|
|
235
235
|
* Reads from the target, passing each chunk to the given block.
|
|
236
236
|
*
|
|
237
|
-
* @return [UringMachine::
|
|
237
|
+
* @return [UringMachine::IO] conn
|
|
238
238
|
*/
|
|
239
|
-
VALUE
|
|
240
|
-
struct
|
|
241
|
-
|
|
239
|
+
VALUE IO_read_each(VALUE self) {
|
|
240
|
+
struct um_io *conn = um_get_io(self);
|
|
241
|
+
io_read_each(conn);
|
|
242
242
|
return self;
|
|
243
243
|
}
|
|
244
244
|
|
|
@@ -251,9 +251,9 @@ VALUE Connection_read_each(VALUE self) {
|
|
|
251
251
|
* @param bufs [Array<String, IO::Buffer>] data to write
|
|
252
252
|
* @return [Integer] total bytes written
|
|
253
253
|
*/
|
|
254
|
-
VALUE
|
|
255
|
-
struct
|
|
256
|
-
return
|
|
254
|
+
VALUE IO_write(int argc, VALUE *argv, VALUE self) {
|
|
255
|
+
struct um_io *conn = um_get_io(self);
|
|
256
|
+
return io_writev(conn, argc, argv);
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
/* call-seq:
|
|
@@ -263,8 +263,8 @@ VALUE Connection_write(int argc, VALUE *argv, VALUE self) {
|
|
|
263
263
|
*
|
|
264
264
|
* @return [any] decoded object
|
|
265
265
|
*/
|
|
266
|
-
VALUE
|
|
267
|
-
struct
|
|
266
|
+
VALUE IO_resp_read(VALUE self) {
|
|
267
|
+
struct um_io *conn = um_get_io(self);
|
|
268
268
|
VALUE out_buffer = rb_utf8_str_new_literal("");
|
|
269
269
|
VALUE obj = resp_read(conn, out_buffer);
|
|
270
270
|
RB_GC_GUARD(out_buffer);
|
|
@@ -280,8 +280,8 @@ VALUE Connection_resp_read(VALUE self) {
|
|
|
280
280
|
* @param obj [any] object to write
|
|
281
281
|
* @return [Integer] total bytes written
|
|
282
282
|
*/
|
|
283
|
-
VALUE
|
|
284
|
-
struct
|
|
283
|
+
VALUE IO_resp_write(VALUE self, VALUE obj) {
|
|
284
|
+
struct um_io *conn = um_get_io(self);
|
|
285
285
|
|
|
286
286
|
VALUE str = rb_str_new(NULL, 0);
|
|
287
287
|
struct um_write_buffer buf;
|
|
@@ -290,7 +290,7 @@ VALUE Connection_resp_write(VALUE self, VALUE obj) {
|
|
|
290
290
|
resp_encode(&buf, obj);
|
|
291
291
|
write_buffer_update_len(&buf);
|
|
292
292
|
|
|
293
|
-
size_t len =
|
|
293
|
+
size_t len = io_write_raw(conn, buf.ptr, buf.len);
|
|
294
294
|
RB_GC_GUARD(str);
|
|
295
295
|
return ULONG2NUM(len);
|
|
296
296
|
}
|
|
@@ -304,7 +304,7 @@ VALUE Connection_resp_write(VALUE self, VALUE obj) {
|
|
|
304
304
|
* @param obj [any] object to be encoded
|
|
305
305
|
* @return [String] str
|
|
306
306
|
*/
|
|
307
|
-
VALUE
|
|
307
|
+
VALUE IO_resp_encode(VALUE self, VALUE str, VALUE obj) {
|
|
308
308
|
struct um_write_buffer buf;
|
|
309
309
|
write_buffer_init(&buf, str);
|
|
310
310
|
rb_str_modify(str);
|
|
@@ -320,8 +320,8 @@ VALUE Connection_resp_encode(VALUE self, VALUE str, VALUE obj) {
|
|
|
320
320
|
*
|
|
321
321
|
* @return [bool] EOF reached
|
|
322
322
|
*/
|
|
323
|
-
VALUE
|
|
324
|
-
struct
|
|
323
|
+
VALUE IO_eof_p(VALUE self) {
|
|
324
|
+
struct um_io *conn = um_get_io(self);
|
|
325
325
|
return conn->eof ? Qtrue : Qfalse;
|
|
326
326
|
}
|
|
327
327
|
|
|
@@ -332,8 +332,8 @@ VALUE Connection_eof_p(VALUE self) {
|
|
|
332
332
|
*
|
|
333
333
|
* @return [Integer] total bytes consumed
|
|
334
334
|
*/
|
|
335
|
-
VALUE
|
|
336
|
-
struct
|
|
335
|
+
VALUE IO_consumed(VALUE self) {
|
|
336
|
+
struct um_io *conn = um_get_io(self);
|
|
337
337
|
return LONG2NUM(conn->consumed_bytes);
|
|
338
338
|
}
|
|
339
339
|
|
|
@@ -344,8 +344,8 @@ VALUE Connection_consumed(VALUE self) {
|
|
|
344
344
|
*
|
|
345
345
|
* @return [Integer] bytes available
|
|
346
346
|
*/
|
|
347
|
-
VALUE
|
|
348
|
-
struct
|
|
347
|
+
VALUE IO_pending(VALUE self) {
|
|
348
|
+
struct um_io *conn = um_get_io(self);
|
|
349
349
|
return LONG2NUM(conn->pending_bytes);
|
|
350
350
|
}
|
|
351
351
|
|
|
@@ -356,37 +356,37 @@ VALUE Connection_pending(VALUE self) {
|
|
|
356
356
|
*
|
|
357
357
|
* @return [UM::Stream] self
|
|
358
358
|
*/
|
|
359
|
-
VALUE
|
|
360
|
-
struct
|
|
361
|
-
|
|
359
|
+
VALUE IO_clear(VALUE self) {
|
|
360
|
+
struct um_io *conn = um_get_io(self);
|
|
361
|
+
io_clear(conn);
|
|
362
362
|
return self;
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
-
void
|
|
366
|
-
|
|
367
|
-
rb_define_alloc_func(
|
|
365
|
+
void Init_IO(void) {
|
|
366
|
+
cIO = rb_define_class_under(cUM, "IO", rb_cObject);
|
|
367
|
+
rb_define_alloc_func(cIO, IO_allocate);
|
|
368
368
|
|
|
369
|
-
rb_define_method(
|
|
370
|
-
rb_define_method(
|
|
369
|
+
rb_define_method(cIO, "initialize", IO_initialize, -1);
|
|
370
|
+
rb_define_method(cIO, "mode", IO_mode, 0);
|
|
371
371
|
|
|
372
|
-
rb_define_method(
|
|
373
|
-
rb_define_method(
|
|
374
|
-
rb_define_method(
|
|
375
|
-
rb_define_method(
|
|
376
|
-
rb_define_method(
|
|
372
|
+
rb_define_method(cIO, "read_line", IO_read_line, 1);
|
|
373
|
+
rb_define_method(cIO, "read", IO_read, 1);
|
|
374
|
+
rb_define_method(cIO, "read_to_delim", IO_read_to_delim, 2);
|
|
375
|
+
rb_define_method(cIO, "skip", IO_skip, 1);
|
|
376
|
+
rb_define_method(cIO, "read_each", IO_read_each, 0);
|
|
377
377
|
|
|
378
|
-
rb_define_method(
|
|
378
|
+
rb_define_method(cIO, "write", IO_write, -1);
|
|
379
379
|
|
|
380
|
-
rb_define_method(
|
|
381
|
-
rb_define_method(
|
|
382
|
-
rb_define_singleton_method(
|
|
380
|
+
rb_define_method(cIO, "resp_read", IO_resp_read, 0);
|
|
381
|
+
rb_define_method(cIO, "resp_write", IO_resp_write, 1);
|
|
382
|
+
rb_define_singleton_method(cIO, "resp_encode", IO_resp_encode, 2);
|
|
383
383
|
|
|
384
|
-
rb_define_method(
|
|
385
|
-
rb_define_method(
|
|
386
|
-
rb_define_method(
|
|
387
|
-
rb_define_method(
|
|
384
|
+
rb_define_method(cIO, "eof?", IO_eof_p, 0);
|
|
385
|
+
rb_define_method(cIO, "consumed", IO_consumed, 0);
|
|
386
|
+
rb_define_method(cIO, "pending", IO_pending, 0);
|
|
387
|
+
rb_define_method(cIO, "clear", IO_clear, 0);
|
|
388
388
|
|
|
389
|
-
|
|
389
|
+
eIORESPError = rb_define_class_under(cIO, "RESPError", rb_eStandardError);
|
|
390
390
|
|
|
391
391
|
SYM_fd = ID2SYM(rb_intern("fd"));
|
|
392
392
|
SYM_socket = ID2SYM(rb_intern("socket"));
|
data/ext/um/um_op.c
CHANGED
|
@@ -20,7 +20,6 @@ const char * um_op_kind_name(enum um_op_kind kind) {
|
|
|
20
20
|
case OP_RECV: return "OP_RECV";
|
|
21
21
|
case OP_RECVMSG: return "OP_RECVMSG";
|
|
22
22
|
case OP_SEND: return "OP_SEND";
|
|
23
|
-
case OP_SEND_BUNDLE: return "OP_SEND_BUNDLE";
|
|
24
23
|
case OP_SENDMSG: return "OP_SENDMSG";
|
|
25
24
|
case OP_SENDV: return "OP_SENDV";
|
|
26
25
|
case OP_SOCKET: return "OP_SOCKET";
|
data/ext/um/um_utils.c
CHANGED
|
@@ -115,92 +115,6 @@ inline int um_get_buffer_bytes_for_writing(VALUE buffer, const void **base, size
|
|
|
115
115
|
return true;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
int um_setup_buffer_ring(struct um *machine, unsigned size, unsigned count) {
|
|
119
|
-
if (machine->buffer_ring_count == BUFFER_RING_MAX_COUNT)
|
|
120
|
-
um_raise_internal_error("Cannot setup more than BUFFER_RING_MAX_COUNT buffer rings");
|
|
121
|
-
|
|
122
|
-
struct buf_ring_descriptor *desc = machine->buffer_rings + machine->buffer_ring_count;
|
|
123
|
-
desc->buf_count = count;
|
|
124
|
-
desc->buf_size = size;
|
|
125
|
-
desc->br_size = sizeof(struct io_uring_buf) * desc->buf_count;
|
|
126
|
-
desc->buf_mask = io_uring_buf_ring_mask(desc->buf_count);
|
|
127
|
-
|
|
128
|
-
void *mapped = mmap(
|
|
129
|
-
NULL, desc->br_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0
|
|
130
|
-
);
|
|
131
|
-
if (mapped == MAP_FAILED)
|
|
132
|
-
um_raise_internal_error("Failed to allocate buffer ring");
|
|
133
|
-
|
|
134
|
-
desc->br = (struct io_uring_buf_ring *)mapped;
|
|
135
|
-
io_uring_buf_ring_init(desc->br);
|
|
136
|
-
|
|
137
|
-
unsigned bg_id = machine->buffer_ring_count;
|
|
138
|
-
int ret;
|
|
139
|
-
desc->br = io_uring_setup_buf_ring(&machine->ring, count, bg_id, 0, &ret);
|
|
140
|
-
if (!desc->br) {
|
|
141
|
-
munmap(desc->br, desc->br_size);
|
|
142
|
-
rb_syserr_fail(-ret, strerror(-ret));
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (size > 0) {
|
|
146
|
-
if (posix_memalign(&desc->buf_base, 4096, desc->buf_count * desc->buf_size)) {
|
|
147
|
-
io_uring_free_buf_ring(&machine->ring, desc->br, desc->buf_count, bg_id);
|
|
148
|
-
um_raise_internal_error("Failed to allocate buffers");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
char *ptr = desc->buf_base;
|
|
152
|
-
for (unsigned i = 0; i < desc->buf_count; i++) {
|
|
153
|
-
io_uring_buf_ring_add(desc->br, ptr, desc->buf_size, i, desc->buf_mask, i);
|
|
154
|
-
ptr += desc->buf_size;
|
|
155
|
-
}
|
|
156
|
-
io_uring_buf_ring_advance(desc->br, desc->buf_count);
|
|
157
|
-
}
|
|
158
|
-
machine->buffer_ring_count++;
|
|
159
|
-
return bg_id;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
inline VALUE um_read_from_buffer_ring(struct um *machine, int bgid, __s32 result, __u32 flags) {
|
|
163
|
-
if (!result) return Qnil;
|
|
164
|
-
|
|
165
|
-
unsigned buf_idx = flags >> IORING_CQE_BUFFER_SHIFT;
|
|
166
|
-
struct buf_ring_descriptor *desc = machine->buffer_rings + bgid;
|
|
167
|
-
char *src = (char *)desc->buf_base + desc->buf_size * buf_idx;
|
|
168
|
-
// TODO: add support for UTF8
|
|
169
|
-
// buf = rd->utf8_encoding ? rb_utf8_str_new(src, cqe->res) : rb_str_new(src, cqe->res);
|
|
170
|
-
VALUE buf = rb_str_new(src, result);
|
|
171
|
-
|
|
172
|
-
// add buffer back to buffer ring
|
|
173
|
-
io_uring_buf_ring_add(
|
|
174
|
-
desc->br, src, desc->buf_size, buf_idx, desc->buf_mask, 0
|
|
175
|
-
);
|
|
176
|
-
io_uring_buf_ring_advance(desc->br, 1);
|
|
177
|
-
|
|
178
|
-
RB_GC_GUARD(buf);
|
|
179
|
-
return buf;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
inline void um_add_strings_to_buffer_ring(struct um *machine, int bgid, VALUE strings) {
|
|
183
|
-
static ID ID_to_s = 0;
|
|
184
|
-
|
|
185
|
-
struct buf_ring_descriptor *desc = machine->buffer_rings + bgid;
|
|
186
|
-
ulong count = RARRAY_LEN(strings);
|
|
187
|
-
VALUE str = Qnil;
|
|
188
|
-
VALUE converted = Qnil;
|
|
189
|
-
|
|
190
|
-
for (ulong i = 0; i < count; i++) {
|
|
191
|
-
str = rb_ary_entry(strings, i);
|
|
192
|
-
if (TYPE(str) != T_STRING) {
|
|
193
|
-
if (!ID_to_s) ID_to_s = rb_intern("to_s");
|
|
194
|
-
if (NIL_P(converted)) converted = rb_ary_new();
|
|
195
|
-
str = rb_funcall(str, ID_to_s, 0);
|
|
196
|
-
rb_ary_push(converted, str);
|
|
197
|
-
}
|
|
198
|
-
io_uring_buf_ring_add(desc->br, RSTRING_PTR(str), RSTRING_LEN(str), i, desc->buf_mask, i);
|
|
199
|
-
}
|
|
200
|
-
RB_GC_GUARD(converted);
|
|
201
|
-
io_uring_buf_ring_advance(desc->br, count);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
118
|
inline void um_raise_internal_error(const char *msg) {
|
|
205
119
|
rb_raise(eUMError, "UringMachine error: %s", msg);
|
|
206
120
|
}
|
data/lib/uringmachine/version.rb
CHANGED
data/lib/uringmachine.rb
CHANGED
|
@@ -195,24 +195,24 @@ class UringMachine
|
|
|
195
195
|
end
|
|
196
196
|
|
|
197
197
|
# call-seq:
|
|
198
|
-
# machine.
|
|
199
|
-
# machine.
|
|
198
|
+
# machine.io(fd, mode = nil) -> conn
|
|
199
|
+
# machine.io(fd, mode = nil) { |conn| }
|
|
200
200
|
#
|
|
201
|
-
# Creates
|
|
202
|
-
#
|
|
201
|
+
# Creates an UM::IO for the given target (fd or SSLSocket). The mode indicates
|
|
202
|
+
# the type of target and how it is read from:
|
|
203
203
|
#
|
|
204
204
|
# - :fd - read from the given fd using the buffer pool (default mode)
|
|
205
205
|
# - :socket - receive from the given socket fd using the buffer pool
|
|
206
|
-
# - :ssl - read from the given SSL
|
|
206
|
+
# - :ssl - read from the given SSL socket
|
|
207
207
|
#
|
|
208
|
-
# If a block is given, the block will be called with the
|
|
209
|
-
# the method will return the block's return value.
|
|
208
|
+
# If a block is given, the block will be called with the IO instance as
|
|
209
|
+
# argument and the method will return the block's return value.
|
|
210
210
|
#
|
|
211
|
-
# @param target [Integer, OpenSSL::SSL::SSLSocket] fd or ssl
|
|
212
|
-
# @param mode [Symbol, nil]
|
|
213
|
-
# @return [UringMachine::
|
|
214
|
-
def
|
|
215
|
-
conn = UM::
|
|
211
|
+
# @param target [Integer, OpenSSL::SSL::SSLSocket] fd or ssl socket
|
|
212
|
+
# @param mode [Symbol, nil] IO mode
|
|
213
|
+
# @return [UringMachine::IO] IO object
|
|
214
|
+
def io(target, mode = nil)
|
|
215
|
+
conn = UM::IO.new(self, target, mode)
|
|
216
216
|
return conn if !block_given?
|
|
217
217
|
|
|
218
218
|
res = yield(conn)
|