iodine 0.6.5 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +4 -4
- data/SPEC-Websocket-Draft.md +3 -6
- data/bin/mustache.rb +128 -0
- data/examples/test_template.mustache +16 -0
- data/ext/iodine/fio.c +9397 -0
- data/ext/iodine/fio.h +4723 -0
- data/ext/iodine/fio_ary.h +353 -54
- data/ext/iodine/fio_cli.c +351 -361
- data/ext/iodine/fio_cli.h +84 -105
- data/ext/iodine/fio_hashmap.h +70 -16
- data/ext/iodine/fio_json_parser.h +35 -24
- data/ext/iodine/fio_siphash.c +104 -4
- data/ext/iodine/fio_siphash.h +18 -2
- data/ext/iodine/fio_str.h +1218 -0
- data/ext/iodine/fio_tmpfile.h +1 -1
- data/ext/iodine/fiobj.h +13 -8
- data/ext/iodine/fiobj4sock.h +6 -8
- data/ext/iodine/fiobj_ary.c +107 -17
- data/ext/iodine/fiobj_ary.h +36 -4
- data/ext/iodine/fiobj_data.c +146 -127
- data/ext/iodine/fiobj_data.h +25 -23
- data/ext/iodine/fiobj_hash.c +7 -7
- data/ext/iodine/fiobj_hash.h +6 -5
- data/ext/iodine/fiobj_json.c +20 -17
- data/ext/iodine/fiobj_json.h +5 -5
- data/ext/iodine/fiobj_mem.h +71 -0
- data/ext/iodine/fiobj_mustache.c +310 -0
- data/ext/iodine/fiobj_mustache.h +40 -0
- data/ext/iodine/fiobj_numbers.c +199 -94
- data/ext/iodine/fiobj_numbers.h +7 -7
- data/ext/iodine/fiobj_str.c +142 -333
- data/ext/iodine/fiobj_str.h +65 -55
- data/ext/iodine/fiobject.c +49 -11
- data/ext/iodine/fiobject.h +40 -39
- data/ext/iodine/http.c +382 -190
- data/ext/iodine/http.h +124 -80
- data/ext/iodine/http1.c +99 -127
- data/ext/iodine/http1.h +5 -5
- data/ext/iodine/http1_parser.c +3 -2
- data/ext/iodine/http1_parser.h +2 -2
- data/ext/iodine/http_internal.c +14 -12
- data/ext/iodine/http_internal.h +25 -19
- data/ext/iodine/iodine.c +37 -18
- data/ext/iodine/iodine.h +4 -0
- data/ext/iodine/iodine_caller.c +9 -2
- data/ext/iodine/iodine_caller.h +2 -0
- data/ext/iodine/iodine_connection.c +82 -117
- data/ext/iodine/iodine_defer.c +57 -50
- data/ext/iodine/iodine_defer.h +0 -1
- data/ext/iodine/iodine_fiobj2rb.h +4 -2
- data/ext/iodine/iodine_helpers.c +4 -4
- data/ext/iodine/iodine_http.c +25 -32
- data/ext/iodine/iodine_json.c +2 -1
- data/ext/iodine/iodine_mustache.c +423 -0
- data/ext/iodine/iodine_mustache.h +6 -0
- data/ext/iodine/iodine_pubsub.c +48 -153
- data/ext/iodine/iodine_pubsub.h +5 -4
- data/ext/iodine/iodine_rack_io.c +7 -5
- data/ext/iodine/iodine_store.c +16 -13
- data/ext/iodine/iodine_tcp.c +26 -34
- data/ext/iodine/mustache_parser.h +1085 -0
- data/ext/iodine/redis_engine.c +740 -646
- data/ext/iodine/redis_engine.h +13 -15
- data/ext/iodine/resp_parser.h +11 -5
- data/ext/iodine/websocket_parser.h +13 -13
- data/ext/iodine/websockets.c +240 -393
- data/ext/iodine/websockets.h +52 -113
- data/lib/iodine.rb +1 -1
- data/lib/iodine/mustache.rb +140 -0
- data/lib/iodine/version.rb +1 -1
- metadata +15 -28
- data/ext/iodine/defer.c +0 -566
- data/ext/iodine/defer.h +0 -148
- data/ext/iodine/evio.c +0 -26
- data/ext/iodine/evio.h +0 -161
- data/ext/iodine/evio_callbacks.c +0 -26
- data/ext/iodine/evio_epoll.c +0 -251
- data/ext/iodine/evio_kqueue.c +0 -194
- data/ext/iodine/facil.c +0 -2325
- data/ext/iodine/facil.h +0 -616
- data/ext/iodine/fio_base64.c +0 -277
- data/ext/iodine/fio_base64.h +0 -71
- data/ext/iodine/fio_llist.h +0 -257
- data/ext/iodine/fio_mem.c +0 -675
- data/ext/iodine/fio_mem.h +0 -143
- data/ext/iodine/fio_random.c +0 -248
- data/ext/iodine/fio_random.h +0 -45
- data/ext/iodine/fio_sha1.c +0 -362
- data/ext/iodine/fio_sha1.h +0 -107
- data/ext/iodine/fio_sha2.c +0 -842
- data/ext/iodine/fio_sha2.h +0 -169
- data/ext/iodine/pubsub.c +0 -867
- data/ext/iodine/pubsub.h +0 -221
- data/ext/iodine/sock.c +0 -1366
- data/ext/iodine/sock.h +0 -566
- data/ext/iodine/spnlock.inc +0 -111
data/ext/iodine/iodine_caller.h
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
#include "iodine_connection.h"
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
3
|
+
#define FIO_INCLUDE_LINKED_LIST
|
4
|
+
#define FIO_INCLUDE_STR
|
5
|
+
#include "fio.h"
|
6
|
+
|
5
7
|
#include "fiobj4sock.h"
|
6
|
-
#include "pubsub.h"
|
7
8
|
#include "websockets.h"
|
8
9
|
|
9
|
-
#include "spnlock.inc"
|
10
|
-
|
11
10
|
#include <ruby/io.h>
|
12
11
|
|
13
12
|
/* *****************************************************************************
|
@@ -41,41 +40,32 @@ static VALUE RAWSymbol;
|
|
41
40
|
Pub/Sub storage
|
42
41
|
***************************************************************************** */
|
43
42
|
|
44
|
-
#define
|
45
|
-
#define
|
46
|
-
#define
|
47
|
-
#define
|
48
|
-
|
49
|
-
|
50
|
-
#define
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
}
|
60
|
-
return Qfalse;
|
43
|
+
#define FIO_SET_NAME fio_subhash
|
44
|
+
#define FIO_SET_OBJ_TYPE subscription_s *
|
45
|
+
#define FIO_SET_KEY_TYPE fio_str_info_s
|
46
|
+
#define FIO_SET_KEY_COMPARE(s1, s2) \
|
47
|
+
((s1).len == (s2).len && \
|
48
|
+
((s1).data == (s2).data || !memcmp((s1).data, (s2).data, (s1).len)))
|
49
|
+
#define FIO_SET_OBJ_DESTROY(obj) fio_unsubscribe((obj))
|
50
|
+
#include <fio.h> // creates the fio_str_set_s Set and functions
|
51
|
+
|
52
|
+
static inline VALUE iodine_sub_unsubscribe(fio_subhash_s *store,
|
53
|
+
fio_str_info_s channel) {
|
54
|
+
if (fio_subhash_remove(store, fio_siphash(channel.data, channel.len),
|
55
|
+
channel))
|
56
|
+
return Qfalse;
|
57
|
+
return Qtrue;
|
61
58
|
}
|
62
|
-
static inline void iodine_sub_add(
|
63
|
-
|
64
|
-
|
65
|
-
if (sub) {
|
66
|
-
pubsub_unsubscribe(sub);
|
67
|
-
}
|
59
|
+
static inline void iodine_sub_add(fio_subhash_s *store, subscription_s *sub) {
|
60
|
+
fio_str_info_s ch = fio_subscription_channel(sub);
|
61
|
+
fio_subhash_insert(store, fio_siphash(ch.data, ch.len), ch, sub);
|
68
62
|
}
|
69
|
-
static inline void iodine_sub_clear_all(
|
70
|
-
|
71
|
-
if (pos->obj) {
|
72
|
-
pubsub_unsubscribe(pos->obj);
|
73
|
-
}
|
74
|
-
}
|
63
|
+
static inline void iodine_sub_clear_all(fio_subhash_s *store) {
|
64
|
+
fio_subhash_free(store);
|
75
65
|
}
|
76
66
|
|
77
|
-
static
|
78
|
-
static
|
67
|
+
static fio_lock_i sub_lock = FIO_LOCK_INIT;
|
68
|
+
static fio_subhash_s sub_global = FIO_SET_INIT;
|
79
69
|
|
80
70
|
/* *****************************************************************************
|
81
71
|
C <=> Ruby Data allocation
|
@@ -84,8 +74,8 @@ C <=> Ruby Data allocation
|
|
84
74
|
typedef struct {
|
85
75
|
iodine_connection_s info;
|
86
76
|
size_t ref;
|
87
|
-
|
88
|
-
|
77
|
+
fio_subhash_s subscriptions;
|
78
|
+
fio_lock_i lock;
|
89
79
|
uint8_t answers_on_message;
|
90
80
|
uint8_t answers_on_drained;
|
91
81
|
uint8_t answers_ping;
|
@@ -113,7 +103,7 @@ static void iodine_connection_data_mark(void *c_) {
|
|
113
103
|
/* a callback for the GC (freeing inactive objects) */
|
114
104
|
static void iodine_connection_data_free(void *c_) {
|
115
105
|
iodine_connection_data_s *data = c_;
|
116
|
-
if (
|
106
|
+
if (fio_atomic_sub(&data->ref, 1))
|
117
107
|
return;
|
118
108
|
free(data);
|
119
109
|
}
|
@@ -142,8 +132,8 @@ static VALUE iodine_connection_data_alloc_c(VALUE self) {
|
|
142
132
|
.info.handler = (VALUE)0,
|
143
133
|
.info.uuid = -1,
|
144
134
|
.ref = 1,
|
145
|
-
.subscriptions =
|
146
|
-
.lock =
|
135
|
+
.subscriptions = FIO_SET_INIT,
|
136
|
+
.lock = FIO_LOCK_INIT,
|
147
137
|
};
|
148
138
|
return TypedData_Wrap_Struct(self, &iodine_connection_data_type, c);
|
149
139
|
}
|
@@ -179,7 +169,7 @@ Ruby Connection Methods - write, close open? pending
|
|
179
169
|
*/
|
180
170
|
static VALUE iodine_connection_write(VALUE self, VALUE data) {
|
181
171
|
iodine_connection_data_s *c = iodine_connection_validate_data(self);
|
182
|
-
if (!c ||
|
172
|
+
if (!c || fio_is_closed(c->info.uuid)) {
|
183
173
|
// don't throw exceptions - closed connections are unavoidable.
|
184
174
|
return Qnil;
|
185
175
|
// rb_raise(rb_eIOError, "Connection closed or invalid.");
|
@@ -187,15 +177,14 @@ static VALUE iodine_connection_write(VALUE self, VALUE data) {
|
|
187
177
|
switch (c->info.type) {
|
188
178
|
case IODINE_CONNECTION_WEBSOCKET:
|
189
179
|
/* WebSockets*/
|
190
|
-
websocket_write(c->info.arg,
|
180
|
+
websocket_write(c->info.arg, IODINE_RSTRINFO(data),
|
191
181
|
rb_enc_get(data) == IodineUTF8Encoding);
|
192
182
|
return Qtrue;
|
193
183
|
break;
|
194
184
|
case IODINE_CONNECTION_SSE:
|
195
185
|
/* SSE */
|
196
186
|
#if 1
|
197
|
-
http_sse_write(c->info.arg, .data =
|
198
|
-
.len = RSTRING_LEN(data)});
|
187
|
+
http_sse_write(c->info.arg, .data = IODINE_RSTRINFO(data));
|
199
188
|
return Qtrue;
|
200
189
|
#else
|
201
190
|
if (rb_enc_get(data) == IodineUTF8Encoding) {
|
@@ -212,14 +201,7 @@ static VALUE iodine_connection_write(VALUE self, VALUE data) {
|
|
212
201
|
break;
|
213
202
|
case IODINE_CONNECTION_RAW: /* fallthrough */
|
214
203
|
default: {
|
215
|
-
|
216
|
-
char *copy = fio_malloc(len);
|
217
|
-
if (!copy) {
|
218
|
-
rb_raise(rb_eNoMemError, "failed to allocate memory for network buffer!");
|
219
|
-
}
|
220
|
-
memcpy(copy, RSTRING_PTR(data), len);
|
221
|
-
sock_write2(.uuid = c->info.uuid, .buffer = copy, .length = len,
|
222
|
-
.dealloc = fio_free);
|
204
|
+
fio_write(c->info.uuid, RSTRING_PTR(data), RSTRING_LEN(data));
|
223
205
|
return Qtrue;
|
224
206
|
} break;
|
225
207
|
}
|
@@ -234,11 +216,11 @@ static VALUE iodine_connection_write(VALUE self, VALUE data) {
|
|
234
216
|
*/
|
235
217
|
static VALUE iodine_connection_close(VALUE self) {
|
236
218
|
iodine_connection_data_s *c = iodine_connection_validate_data(self);
|
237
|
-
if (c && !
|
219
|
+
if (c && !fio_is_closed(c->info.uuid)) {
|
238
220
|
if (c->info.type == IODINE_CONNECTION_WEBSOCKET) {
|
239
221
|
websocket_close(c->info.arg); /* sends WebSocket close packet */
|
240
222
|
} else {
|
241
|
-
|
223
|
+
fio_close(c->info.uuid);
|
242
224
|
}
|
243
225
|
}
|
244
226
|
|
@@ -247,7 +229,7 @@ static VALUE iodine_connection_close(VALUE self) {
|
|
247
229
|
/** Returns true if the connection appears to be open (no known issues). */
|
248
230
|
static VALUE iodine_connection_is_open(VALUE self) {
|
249
231
|
iodine_connection_data_s *c = iodine_connection_validate_data(self);
|
250
|
-
if (c && !
|
232
|
+
if (c && !fio_is_closed(c->info.uuid)) {
|
251
233
|
return Qtrue;
|
252
234
|
}
|
253
235
|
return Qfalse;
|
@@ -261,10 +243,10 @@ static VALUE iodine_connection_is_open(VALUE self) {
|
|
261
243
|
*/
|
262
244
|
static VALUE iodine_connection_pending(VALUE self) {
|
263
245
|
iodine_connection_data_s *c = iodine_connection_validate_data(self);
|
264
|
-
if (!c ||
|
246
|
+
if (!c || fio_is_closed(c->info.uuid)) {
|
265
247
|
return INT2NUM(-1);
|
266
248
|
}
|
267
|
-
return SIZET2NUM((
|
249
|
+
return SIZET2NUM((fio_pending(c->info.uuid)));
|
268
250
|
}
|
269
251
|
|
270
252
|
/** Returns the connection's protocol Symbol (`:sse`, `:websocket`, etc'). */
|
@@ -293,8 +275,8 @@ static VALUE iodine_connection_protocol_name(VALUE self) {
|
|
293
275
|
*/
|
294
276
|
static VALUE iodine_connection_timeout_get(VALUE self) {
|
295
277
|
iodine_connection_data_s *c = iodine_connection_validate_data(self);
|
296
|
-
if (c && !
|
297
|
-
size_t tout = (size_t)
|
278
|
+
if (c && !fio_is_closed(c->info.uuid)) {
|
279
|
+
size_t tout = (size_t)fio_timeout_get(c->info.uuid);
|
298
280
|
return SIZET2NUM(tout);
|
299
281
|
}
|
300
282
|
return Qnil;
|
@@ -313,8 +295,8 @@ static VALUE iodine_connection_timeout_set(VALUE self, VALUE timeout) {
|
|
313
295
|
return Qnil;
|
314
296
|
}
|
315
297
|
iodine_connection_data_s *c = iodine_connection_validate_data(self);
|
316
|
-
if (c && !
|
317
|
-
|
298
|
+
if (c && !fio_is_closed(c->info.uuid)) {
|
299
|
+
fio_timeout_set(c->info.uuid, (uint8_t)tout);
|
318
300
|
return timeout;
|
319
301
|
}
|
320
302
|
return Qnil;
|
@@ -337,38 +319,34 @@ Pub/Sub Callbacks (internal implementation)
|
|
337
319
|
|
338
320
|
/* calls the Ruby block assigned to a pubsub event (within the GVL). */
|
339
321
|
static void *iodine_on_pubsub_call_block(void *msg_) {
|
340
|
-
|
341
|
-
fio_cstr_s tmp;
|
322
|
+
fio_msg_s *msg = msg_;
|
342
323
|
VALUE args[2];
|
343
|
-
|
344
|
-
args[
|
345
|
-
tmp = fiobj_obj2cstr(msg->message);
|
346
|
-
args[1] = rb_str_new(tmp.data, tmp.len);
|
324
|
+
args[0] = rb_str_new(msg->channel.data, msg->channel.len);
|
325
|
+
args[1] = rb_str_new(msg->msg.data, msg->msg.len);
|
347
326
|
IodineCaller.call2((VALUE)msg->udata2, call_id, 2, args);
|
348
327
|
return NULL;
|
349
328
|
}
|
350
329
|
|
351
330
|
/* callback for incoming subscription messages */
|
352
|
-
static void iodine_on_pubsub(
|
331
|
+
static void iodine_on_pubsub(fio_msg_s *msg) {
|
353
332
|
iodine_connection_data_s *data = msg->udata1;
|
354
333
|
VALUE block = (VALUE)msg->udata2;
|
355
334
|
switch (block) {
|
356
335
|
case Qnil: /* fallthrough */
|
357
336
|
case Qtrue: {
|
358
337
|
if (data->info.handler == Qnil || data->info.uuid == -1 ||
|
359
|
-
|
338
|
+
fio_is_closed(data->info.uuid))
|
360
339
|
return;
|
361
340
|
switch (data->info.type) {
|
362
341
|
case IODINE_CONNECTION_WEBSOCKET: {
|
363
|
-
|
364
|
-
websocket_write(data->info.arg, str.data, str.len, (block == Qnil));
|
342
|
+
websocket_write(data->info.arg, msg->msg, (block == Qnil));
|
365
343
|
return;
|
366
344
|
}
|
367
345
|
case IODINE_CONNECTION_SSE:
|
368
|
-
http_sse_write(data->info.arg, .data =
|
346
|
+
http_sse_write(data->info.arg, .data = msg->msg);
|
369
347
|
return;
|
370
348
|
default:
|
371
|
-
|
349
|
+
fio_write(data->info.uuid, msg->msg.data, msg->msg.len);
|
372
350
|
return;
|
373
351
|
}
|
374
352
|
}
|
@@ -402,8 +380,8 @@ Ruby Connection Methods - Pub/Sub
|
|
402
380
|
typedef struct {
|
403
381
|
VALUE channel;
|
404
382
|
VALUE block;
|
383
|
+
fio_match_fn pattern;
|
405
384
|
uint8_t binary;
|
406
|
-
uint8_t pattern;
|
407
385
|
} iodine_sub_args_s;
|
408
386
|
|
409
387
|
/** Tests the `subscribe` Ruby arguments */
|
@@ -454,7 +432,7 @@ static iodine_sub_args_s iodine_subscribe_args(int argc, VALUE *argv) {
|
|
454
432
|
ret.binary = 1;
|
455
433
|
}
|
456
434
|
if (rb_hash_aref(rb_opt, match_id) == redis_id) {
|
457
|
-
ret.pattern =
|
435
|
+
ret.pattern = FIO_MATCH_GLOB;
|
458
436
|
}
|
459
437
|
ret.block = rb_hash_aref(rb_opt, handler_id);
|
460
438
|
if (ret.block != Qnil) {
|
@@ -527,31 +505,28 @@ static VALUE iodine_pubsub_subscribe(int argc, VALUE *argv, VALUE self) {
|
|
527
505
|
if (args.block == Qnil && args.binary) {
|
528
506
|
args.block = Qtrue;
|
529
507
|
}
|
530
|
-
|
508
|
+
fio_atomic_add(&c->ref, 1);
|
531
509
|
}
|
532
510
|
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
.udata2 = (void *)args.block,
|
539
|
-
.use_pattern = args.pattern);
|
540
|
-
fiobj_free(channel);
|
511
|
+
subscription_s *sub =
|
512
|
+
fio_subscribe(.channel = IODINE_RSTRINFO(args.channel),
|
513
|
+
.on_message = iodine_on_pubsub,
|
514
|
+
.on_unsubscribe = iodine_on_unsubscribe, .udata1 = c,
|
515
|
+
.udata2 = (void *)args.block, .match = args.pattern);
|
541
516
|
if (c) {
|
542
|
-
|
517
|
+
fio_lock(&c->lock);
|
543
518
|
if (c->info.uuid == -1) {
|
544
|
-
|
545
|
-
|
519
|
+
fio_unsubscribe(sub);
|
520
|
+
fio_unlock(&c->lock);
|
546
521
|
return Qnil;
|
547
522
|
} else {
|
548
523
|
iodine_sub_add(&c->subscriptions, sub);
|
549
524
|
}
|
550
|
-
|
525
|
+
fio_unlock(&c->lock);
|
551
526
|
} else {
|
552
|
-
|
527
|
+
fio_lock(&sub_lock);
|
553
528
|
iodine_sub_add(&sub_global, sub);
|
554
|
-
|
529
|
+
fio_unlock(&sub_lock);
|
555
530
|
}
|
556
531
|
return args.channel;
|
557
532
|
}
|
@@ -572,22 +547,20 @@ Returns `false` if the subscription didn't exist.
|
|
572
547
|
static VALUE iodine_pubsub_unsubscribe(VALUE self, VALUE name) {
|
573
548
|
// clang-format on
|
574
549
|
iodine_connection_data_s *c = NULL;
|
575
|
-
FIOBJ channel = fiobj_str_new(RSTRING_PTR(name), RSTRING_LEN(name));
|
576
550
|
VALUE ret;
|
577
551
|
if (TYPE(self) == T_MODULE) {
|
578
|
-
|
579
|
-
ret = iodine_sub_unsubscribe(&sub_global,
|
580
|
-
|
552
|
+
fio_lock(&sub_lock);
|
553
|
+
ret = iodine_sub_unsubscribe(&sub_global, IODINE_RSTRINFO(name));
|
554
|
+
fio_unlock(&sub_lock);
|
581
555
|
} else {
|
582
556
|
c = iodine_connection_validate_data(self);
|
583
557
|
if (!c) {
|
584
|
-
return Qnil; /* cannot
|
558
|
+
return Qnil; /* cannot unsubscribe a closed connection. */
|
585
559
|
}
|
586
|
-
|
587
|
-
ret = iodine_sub_unsubscribe(&sub_global,
|
588
|
-
|
560
|
+
fio_lock(&sub_lock);
|
561
|
+
ret = iodine_sub_unsubscribe(&sub_global, IODINE_RSTRINFO(name));
|
562
|
+
fio_unlock(&sub_lock);
|
589
563
|
}
|
590
|
-
fiobj_free(channel);
|
591
564
|
return ret;
|
592
565
|
}
|
593
566
|
|
@@ -616,7 +589,7 @@ Alternatively, accepts the following named arguments:
|
|
616
589
|
static VALUE iodine_pubsub_publish(int argc, VALUE *argv, VALUE self) {
|
617
590
|
// clang-format on
|
618
591
|
VALUE rb_ch, rb_msg, rb_engine = Qnil;
|
619
|
-
const
|
592
|
+
const fio_pubsub_engine_s *engine = NULL;
|
620
593
|
switch (argc) {
|
621
594
|
case 3:
|
622
595
|
/* fallthrough */
|
@@ -651,7 +624,7 @@ static VALUE iodine_pubsub_publish(int argc, VALUE *argv, VALUE self) {
|
|
651
624
|
Check_Type(rb_ch, T_STRING);
|
652
625
|
|
653
626
|
if (rb_engine == Qfalse) {
|
654
|
-
engine =
|
627
|
+
engine = FIO_PUBSUB_PROCESS;
|
655
628
|
} else if (rb_engine != Qnil) {
|
656
629
|
// collect engine object
|
657
630
|
iodine_pubsub_s *e = iodine_pubsub_CData(rb_engine);
|
@@ -660,15 +633,8 @@ static VALUE iodine_pubsub_publish(int argc, VALUE *argv, VALUE self) {
|
|
660
633
|
}
|
661
634
|
}
|
662
635
|
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
intptr_t ret =
|
667
|
-
pubsub_publish(.engine = engine, .channel = ch, .message = msg);
|
668
|
-
fiobj_free(ch);
|
669
|
-
fiobj_free(msg);
|
670
|
-
if (!ret)
|
671
|
-
return Qfalse;
|
636
|
+
fio_publish(.engine = engine, .channel = IODINE_RSTRINFO(rb_ch),
|
637
|
+
.message = IODINE_RSTRINFO(rb_msg));
|
672
638
|
return Qtrue;
|
673
639
|
(void)self;
|
674
640
|
}
|
@@ -693,7 +659,7 @@ VALUE iodine_connection_new(iodine_connection_s args) {
|
|
693
659
|
}
|
694
660
|
*data = (iodine_connection_data_s){
|
695
661
|
.info = args,
|
696
|
-
.subscriptions =
|
662
|
+
.subscriptions = FIO_SET_INIT,
|
697
663
|
.ref = 1,
|
698
664
|
.answers_on_open = (rb_respond_to(args.handler, on_open_id) != 0),
|
699
665
|
.answers_on_message = (rb_respond_to(args.handler, on_message_id) != 0),
|
@@ -701,7 +667,7 @@ VALUE iodine_connection_new(iodine_connection_s args) {
|
|
701
667
|
.answers_on_drained = (rb_respond_to(args.handler, on_drained_id) != 0),
|
702
668
|
.answers_on_shutdown = (rb_respond_to(args.handler, on_shutdown_id) != 0),
|
703
669
|
.answers_on_close = (rb_respond_to(args.handler, on_close_id) != 0),
|
704
|
-
.lock =
|
670
|
+
.lock = FIO_LOCK_INIT,
|
705
671
|
};
|
706
672
|
return connection;
|
707
673
|
}
|
@@ -756,13 +722,13 @@ void iodine_connection_fire_event(VALUE connection,
|
|
756
722
|
if (data->answers_on_close) {
|
757
723
|
IodineCaller.call2(data->info.handler, on_close_id, 1, args);
|
758
724
|
}
|
759
|
-
|
725
|
+
fio_lock(&data->lock);
|
760
726
|
data->info.handler = Qnil;
|
761
727
|
data->info.env = Qnil;
|
762
728
|
data->info.uuid = -1;
|
763
729
|
data->info.arg = NULL;
|
764
730
|
iodine_sub_clear_all(&data->subscriptions);
|
765
|
-
|
731
|
+
fio_unlock(&data->lock);
|
766
732
|
IodineStore.remove(connection);
|
767
733
|
break;
|
768
734
|
default:
|
@@ -821,8 +787,7 @@ void iodine_connection_init(void) {
|
|
821
787
|
IodineStore.add(RAWSymbol);
|
822
788
|
|
823
789
|
// define the Connection Class and it's methods
|
824
|
-
ConnectionKlass =
|
825
|
-
rb_define_class_under(IodineModule, "Connection", rb_cObject);
|
790
|
+
ConnectionKlass = rb_define_class_under(IodineModule, "Connection", rb_cData);
|
826
791
|
rb_define_alloc_func(ConnectionKlass, iodine_connection_data_alloc_c);
|
827
792
|
rb_define_method(ConnectionKlass, "write", iodine_connection_write, 1);
|
828
793
|
rb_define_method(ConnectionKlass, "close", iodine_connection_close, 0);
|
data/ext/iodine/iodine_defer.c
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
#include <stdint.h>
|
6
6
|
// clang-format on
|
7
7
|
|
8
|
-
#
|
9
|
-
#include
|
8
|
+
#define FIO_INCLUDE_LINKED_LIST
|
9
|
+
#include "fio.h"
|
10
10
|
|
11
11
|
#include <pthread.h>
|
12
12
|
|
@@ -14,7 +14,7 @@
|
|
14
14
|
IO flushing dedicated thread for protection against blocking code
|
15
15
|
***************************************************************************** */
|
16
16
|
|
17
|
-
static
|
17
|
+
static fio_lock_i sock_io_thread = 0;
|
18
18
|
static pthread_t sock_io_pthread;
|
19
19
|
typedef struct {
|
20
20
|
size_t threads;
|
@@ -23,26 +23,29 @@ typedef struct {
|
|
23
23
|
|
24
24
|
static void *iodine_io_thread(void *arg) {
|
25
25
|
(void)arg;
|
26
|
-
struct timespec tm;
|
27
26
|
while (sock_io_thread) {
|
28
|
-
|
29
|
-
|
30
|
-
nanosleep(&tm, NULL);
|
27
|
+
fio_flush_all();
|
28
|
+
fio_throttle_thread(100);
|
31
29
|
}
|
32
30
|
return NULL;
|
33
31
|
}
|
34
|
-
static void iodine_start_io_thread(void *a_
|
35
|
-
if (!
|
32
|
+
static void iodine_start_io_thread(void *a_) {
|
33
|
+
if (!fio_atomic_add(&sock_io_thread, 1)) {
|
36
34
|
pthread_create(&sock_io_pthread, NULL, iodine_io_thread, NULL);
|
37
35
|
}
|
38
36
|
(void)a_;
|
37
|
+
}
|
38
|
+
|
39
|
+
static void iodine_start_io_thread2(void *a_, void *b_) {
|
40
|
+
iodine_start_io_thread(a_);
|
39
41
|
(void)b_;
|
40
42
|
}
|
43
|
+
|
41
44
|
static void iodine_join_io_thread(void) {
|
42
|
-
if (
|
45
|
+
if (fio_atomic_sub(&sock_io_thread, 1) == 0) {
|
43
46
|
sock_io_thread = 0;
|
44
47
|
pthread_join(sock_io_pthread, NULL);
|
45
|
-
sock_io_pthread = NULL;
|
48
|
+
sock_io_pthread = (pthread_t)NULL;
|
46
49
|
}
|
47
50
|
}
|
48
51
|
|
@@ -54,11 +57,14 @@ The Defer library overriding functions
|
|
54
57
|
struct CreateThreadArgs {
|
55
58
|
void *(*thread_func)(void *);
|
56
59
|
void *arg;
|
57
|
-
|
60
|
+
fio_lock_i lock;
|
58
61
|
};
|
59
62
|
|
60
63
|
/* used for GVL signalling */
|
61
|
-
void call_async_signal(void *pool) {
|
64
|
+
void call_async_signal(void *pool) {
|
65
|
+
fio_stop();
|
66
|
+
(void)pool;
|
67
|
+
}
|
62
68
|
|
63
69
|
static void *defer_thread_start(void *args_) {
|
64
70
|
struct CreateThreadArgs *args = args_;
|
@@ -72,7 +78,7 @@ static VALUE defer_thread_inGVL(void *args_) {
|
|
72
78
|
struct CreateThreadArgs *old_args = args_;
|
73
79
|
struct CreateThreadArgs args = *old_args;
|
74
80
|
IodineCaller.set_GVL(1);
|
75
|
-
|
81
|
+
fio_unlock(&old_args->lock);
|
76
82
|
rb_thread_call_without_gvl(defer_thread_start, &args,
|
77
83
|
(void (*)(void *))call_async_signal, args.arg);
|
78
84
|
return Qnil;
|
@@ -108,7 +114,7 @@ static void *fork_using_ruby(void *ignr) {
|
|
108
114
|
}
|
109
115
|
iodine_perform_fork_callbacks(0);
|
110
116
|
// re-initiate IO thread
|
111
|
-
|
117
|
+
fio_defer(iodine_start_io_thread2, NULL, NULL);
|
112
118
|
return (void *)pid;
|
113
119
|
(void)ignr;
|
114
120
|
}
|
@@ -116,17 +122,19 @@ static void *fork_using_ruby(void *ignr) {
|
|
116
122
|
/**
|
117
123
|
OVERRIDE THIS to replace the default pthread implementation.
|
118
124
|
*/
|
119
|
-
void *
|
125
|
+
void *fio_thread_new(void *(*thread_func)(void *), void *arg) {
|
120
126
|
struct CreateThreadArgs data = (struct CreateThreadArgs){
|
121
|
-
.thread_func = thread_func,
|
127
|
+
.thread_func = thread_func,
|
128
|
+
.arg = arg,
|
129
|
+
.lock = FIO_LOCK_INIT,
|
122
130
|
};
|
123
|
-
|
131
|
+
fio_lock(&data.lock);
|
124
132
|
void *thr = IodineCaller.enterGVL(create_ruby_thread_gvl, &data);
|
125
133
|
if (!thr || thr == (void *)Qnil || thr == (void *)Qfalse) {
|
126
134
|
thr = NULL;
|
127
135
|
} else {
|
128
136
|
/* wait for thread to signal it's alive. */
|
129
|
-
|
137
|
+
fio_lock(&data.lock);
|
130
138
|
}
|
131
139
|
return thr;
|
132
140
|
}
|
@@ -134,7 +142,7 @@ void *defer_new_thread(void *(*thread_func)(void *), void *arg) {
|
|
134
142
|
/**
|
135
143
|
OVERRIDE THIS to replace the default pthread implementation.
|
136
144
|
*/
|
137
|
-
int
|
145
|
+
int fio_thread_join(void *thr) {
|
138
146
|
if (!thr || (VALUE)thr == Qfalse || (VALUE)thr == Qnil)
|
139
147
|
return -1;
|
140
148
|
IodineCaller.call((VALUE)thr, rb_intern("join"));
|
@@ -143,7 +151,7 @@ int defer_join_thread(void *thr) {
|
|
143
151
|
}
|
144
152
|
|
145
153
|
// void defer_free_thread(void *thr) { (void)thr; }
|
146
|
-
void
|
154
|
+
void fio_thread_free(void *thr) { IodineStore.remove((VALUE)thr); }
|
147
155
|
|
148
156
|
/**
|
149
157
|
OVERRIDE THIS to replace the default `fork` implementation or to inject hooks
|
@@ -151,7 +159,7 @@ into the forking function.
|
|
151
159
|
|
152
160
|
Behaves like the system's `fork`.
|
153
161
|
*/
|
154
|
-
int
|
162
|
+
int fio_fork(void) {
|
155
163
|
intptr_t pid = (intptr_t)IodineCaller.enterGVL(fork_using_ruby, NULL);
|
156
164
|
return (int)pid;
|
157
165
|
}
|
@@ -189,7 +197,7 @@ Defer API
|
|
189
197
|
static VALUE iodine_defer_run(VALUE self) {
|
190
198
|
rb_need_block();
|
191
199
|
VALUE block = IodineStore.add(rb_block_proc());
|
192
|
-
|
200
|
+
fio_defer(iodine_defer_performe_once, (void *)block, NULL);
|
193
201
|
return block;
|
194
202
|
(void)self;
|
195
203
|
}
|
@@ -221,8 +229,8 @@ static VALUE iodine_defer_run_after(VALUE self, VALUE milliseconds) {
|
|
221
229
|
if (block == Qnil)
|
222
230
|
return Qfalse;
|
223
231
|
IodineStore.add(block);
|
224
|
-
if (
|
225
|
-
|
232
|
+
if (fio_run_every(milli, 1, iodine_defer_run_timer, (void *)block,
|
233
|
+
(void (*)(void *))IodineStore.remove) == -1) {
|
226
234
|
perror("ERROR: Iodine couldn't initialize timer");
|
227
235
|
return Qnil;
|
228
236
|
}
|
@@ -265,8 +273,8 @@ static VALUE iodine_defer_run_every(int argc, VALUE *argv, VALUE self) {
|
|
265
273
|
// requires a block to be passed
|
266
274
|
rb_need_block();
|
267
275
|
IodineStore.add(block);
|
268
|
-
if (
|
269
|
-
|
276
|
+
if (fio_run_every(milli, repeat, iodine_defer_run_timer, (void *)block,
|
277
|
+
(void (*)(void *))IodineStore.remove) == -1) {
|
270
278
|
perror("ERROR: Iodine couldn't initialize timer");
|
271
279
|
return Qnil;
|
272
280
|
}
|
@@ -276,14 +284,12 @@ static VALUE iodine_defer_run_every(int argc, VALUE *argv, VALUE self) {
|
|
276
284
|
/* *****************************************************************************
|
277
285
|
Pre/Post `fork`
|
278
286
|
***************************************************************************** */
|
279
|
-
#include "fio_llist.h"
|
280
|
-
#include "spnlock.inc"
|
281
287
|
|
282
|
-
static
|
288
|
+
static fio_lock_i iodine_before_fork_lock = FIO_LOCK_INIT;
|
283
289
|
static fio_ls_s iodine_before_fork_list = FIO_LS_INIT(iodine_before_fork_list);
|
284
|
-
static
|
290
|
+
static fio_lock_i iodine_after_fork_lock = FIO_LOCK_INIT;
|
285
291
|
static fio_ls_s iodine_after_fork_list = FIO_LS_INIT(iodine_after_fork_list);
|
286
|
-
static
|
292
|
+
static fio_lock_i iodine_on_shutdown_lock = FIO_LOCK_INIT;
|
287
293
|
static fio_ls_s iodine_on_shutdown_list = FIO_LS_INIT(iodine_on_shutdown_list);
|
288
294
|
|
289
295
|
/**
|
@@ -294,9 +300,9 @@ VALUE iodine_before_fork_add(VALUE self) {
|
|
294
300
|
rb_need_block();
|
295
301
|
VALUE block = rb_block_proc();
|
296
302
|
IodineStore.add(block);
|
297
|
-
|
303
|
+
fio_lock(&iodine_before_fork_lock);
|
298
304
|
fio_ls_push(&iodine_before_fork_list, (void *)block);
|
299
|
-
|
305
|
+
fio_unlock(&iodine_before_fork_lock);
|
300
306
|
return block;
|
301
307
|
(void)self;
|
302
308
|
}
|
@@ -309,9 +315,9 @@ VALUE iodine_after_fork_add(VALUE self) {
|
|
309
315
|
rb_need_block();
|
310
316
|
VALUE block = rb_block_proc();
|
311
317
|
IodineStore.add(block);
|
312
|
-
|
318
|
+
fio_lock(&iodine_after_fork_lock);
|
313
319
|
fio_ls_push(&iodine_after_fork_list, (void *)block);
|
314
|
-
|
320
|
+
fio_unlock(&iodine_after_fork_lock);
|
315
321
|
return block;
|
316
322
|
(void)self;
|
317
323
|
}
|
@@ -325,9 +331,9 @@ VALUE iodine_on_shutdown_add(VALUE self) {
|
|
325
331
|
rb_need_block();
|
326
332
|
VALUE block = rb_block_proc();
|
327
333
|
IodineStore.add(block);
|
328
|
-
|
334
|
+
fio_lock(&iodine_on_shutdown_lock);
|
329
335
|
fio_ls_push(&iodine_on_shutdown_list, (void *)block);
|
330
|
-
|
336
|
+
fio_unlock(&iodine_on_shutdown_lock);
|
331
337
|
return block;
|
332
338
|
(void)self;
|
333
339
|
}
|
@@ -335,37 +341,37 @@ VALUE iodine_on_shutdown_add(VALUE self) {
|
|
335
341
|
/* Runs the before / after fork callbacks (if `before` is true, before runs) */
|
336
342
|
static void iodine_perform_fork_callbacks(uint8_t before) {
|
337
343
|
fio_ls_s *ls = before ? &iodine_before_fork_list : &iodine_after_fork_list;
|
338
|
-
|
344
|
+
fio_lock_i *lock =
|
339
345
|
before ? &iodine_before_fork_lock : &iodine_after_fork_lock;
|
340
|
-
|
346
|
+
fio_lock(lock);
|
341
347
|
FIO_LS_FOR(ls, pos) { IodineCaller.call((VALUE)(pos->obj), call_id); }
|
342
|
-
|
348
|
+
fio_unlock(lock);
|
343
349
|
}
|
344
350
|
|
345
351
|
/* Performs any cleanup before worker dies */
|
346
|
-
void iodine_defer_on_finish(void) {
|
352
|
+
static void iodine_defer_on_finish(void *ignr) {
|
353
|
+
(void)ignr;
|
347
354
|
iodine_join_io_thread();
|
348
355
|
/* perform and clear away shutdown Procs */
|
349
|
-
|
356
|
+
fio_lock(&iodine_on_shutdown_lock);
|
350
357
|
while (fio_ls_any(&iodine_on_shutdown_list)) {
|
351
358
|
void *obj = fio_ls_shift(&iodine_on_shutdown_list);
|
352
359
|
IodineCaller.call((VALUE)(obj), call_id);
|
353
360
|
IodineStore.remove((VALUE)(obj));
|
354
361
|
}
|
355
|
-
|
362
|
+
fio_unlock(&iodine_on_shutdown_lock);
|
356
363
|
/* clear away forking Procs */
|
357
|
-
|
364
|
+
fio_lock(&iodine_before_fork_lock);
|
358
365
|
while (fio_ls_any(&iodine_before_fork_list)) {
|
359
366
|
IodineStore.remove((VALUE)fio_ls_shift(&iodine_before_fork_list));
|
360
367
|
}
|
361
|
-
|
368
|
+
fio_unlock(&iodine_before_fork_lock);
|
362
369
|
|
363
|
-
|
370
|
+
fio_lock(&iodine_after_fork_lock);
|
364
371
|
while (fio_ls_any(&iodine_after_fork_list)) {
|
365
372
|
IodineStore.remove((VALUE)fio_ls_shift(&iodine_after_fork_list));
|
366
|
-
void *obj = fio_ls_shift(&iodine_after_fork_list);
|
367
373
|
}
|
368
|
-
|
374
|
+
fio_unlock(&iodine_after_fork_lock);
|
369
375
|
}
|
370
376
|
|
371
377
|
/* *****************************************************************************
|
@@ -387,5 +393,6 @@ void iodine_defer_initialize(void) {
|
|
387
393
|
0);
|
388
394
|
rb_define_module_function(IodineModule, "on_shutdown", iodine_on_shutdown_add,
|
389
395
|
0);
|
390
|
-
|
396
|
+
fio_state_callback_add(FIO_CALL_ON_FINISH, iodine_defer_on_finish, NULL);
|
397
|
+
fio_state_callback_add(FIO_CALL_PRE_START, iodine_start_io_thread, NULL);
|
391
398
|
}
|