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.

Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +4 -4
  4. data/SPEC-Websocket-Draft.md +3 -6
  5. data/bin/mustache.rb +128 -0
  6. data/examples/test_template.mustache +16 -0
  7. data/ext/iodine/fio.c +9397 -0
  8. data/ext/iodine/fio.h +4723 -0
  9. data/ext/iodine/fio_ary.h +353 -54
  10. data/ext/iodine/fio_cli.c +351 -361
  11. data/ext/iodine/fio_cli.h +84 -105
  12. data/ext/iodine/fio_hashmap.h +70 -16
  13. data/ext/iodine/fio_json_parser.h +35 -24
  14. data/ext/iodine/fio_siphash.c +104 -4
  15. data/ext/iodine/fio_siphash.h +18 -2
  16. data/ext/iodine/fio_str.h +1218 -0
  17. data/ext/iodine/fio_tmpfile.h +1 -1
  18. data/ext/iodine/fiobj.h +13 -8
  19. data/ext/iodine/fiobj4sock.h +6 -8
  20. data/ext/iodine/fiobj_ary.c +107 -17
  21. data/ext/iodine/fiobj_ary.h +36 -4
  22. data/ext/iodine/fiobj_data.c +146 -127
  23. data/ext/iodine/fiobj_data.h +25 -23
  24. data/ext/iodine/fiobj_hash.c +7 -7
  25. data/ext/iodine/fiobj_hash.h +6 -5
  26. data/ext/iodine/fiobj_json.c +20 -17
  27. data/ext/iodine/fiobj_json.h +5 -5
  28. data/ext/iodine/fiobj_mem.h +71 -0
  29. data/ext/iodine/fiobj_mustache.c +310 -0
  30. data/ext/iodine/fiobj_mustache.h +40 -0
  31. data/ext/iodine/fiobj_numbers.c +199 -94
  32. data/ext/iodine/fiobj_numbers.h +7 -7
  33. data/ext/iodine/fiobj_str.c +142 -333
  34. data/ext/iodine/fiobj_str.h +65 -55
  35. data/ext/iodine/fiobject.c +49 -11
  36. data/ext/iodine/fiobject.h +40 -39
  37. data/ext/iodine/http.c +382 -190
  38. data/ext/iodine/http.h +124 -80
  39. data/ext/iodine/http1.c +99 -127
  40. data/ext/iodine/http1.h +5 -5
  41. data/ext/iodine/http1_parser.c +3 -2
  42. data/ext/iodine/http1_parser.h +2 -2
  43. data/ext/iodine/http_internal.c +14 -12
  44. data/ext/iodine/http_internal.h +25 -19
  45. data/ext/iodine/iodine.c +37 -18
  46. data/ext/iodine/iodine.h +4 -0
  47. data/ext/iodine/iodine_caller.c +9 -2
  48. data/ext/iodine/iodine_caller.h +2 -0
  49. data/ext/iodine/iodine_connection.c +82 -117
  50. data/ext/iodine/iodine_defer.c +57 -50
  51. data/ext/iodine/iodine_defer.h +0 -1
  52. data/ext/iodine/iodine_fiobj2rb.h +4 -2
  53. data/ext/iodine/iodine_helpers.c +4 -4
  54. data/ext/iodine/iodine_http.c +25 -32
  55. data/ext/iodine/iodine_json.c +2 -1
  56. data/ext/iodine/iodine_mustache.c +423 -0
  57. data/ext/iodine/iodine_mustache.h +6 -0
  58. data/ext/iodine/iodine_pubsub.c +48 -153
  59. data/ext/iodine/iodine_pubsub.h +5 -4
  60. data/ext/iodine/iodine_rack_io.c +7 -5
  61. data/ext/iodine/iodine_store.c +16 -13
  62. data/ext/iodine/iodine_tcp.c +26 -34
  63. data/ext/iodine/mustache_parser.h +1085 -0
  64. data/ext/iodine/redis_engine.c +740 -646
  65. data/ext/iodine/redis_engine.h +13 -15
  66. data/ext/iodine/resp_parser.h +11 -5
  67. data/ext/iodine/websocket_parser.h +13 -13
  68. data/ext/iodine/websockets.c +240 -393
  69. data/ext/iodine/websockets.h +52 -113
  70. data/lib/iodine.rb +1 -1
  71. data/lib/iodine/mustache.rb +140 -0
  72. data/lib/iodine/version.rb +1 -1
  73. metadata +15 -28
  74. data/ext/iodine/defer.c +0 -566
  75. data/ext/iodine/defer.h +0 -148
  76. data/ext/iodine/evio.c +0 -26
  77. data/ext/iodine/evio.h +0 -161
  78. data/ext/iodine/evio_callbacks.c +0 -26
  79. data/ext/iodine/evio_epoll.c +0 -251
  80. data/ext/iodine/evio_kqueue.c +0 -194
  81. data/ext/iodine/facil.c +0 -2325
  82. data/ext/iodine/facil.h +0 -616
  83. data/ext/iodine/fio_base64.c +0 -277
  84. data/ext/iodine/fio_base64.h +0 -71
  85. data/ext/iodine/fio_llist.h +0 -257
  86. data/ext/iodine/fio_mem.c +0 -675
  87. data/ext/iodine/fio_mem.h +0 -143
  88. data/ext/iodine/fio_random.c +0 -248
  89. data/ext/iodine/fio_random.h +0 -45
  90. data/ext/iodine/fio_sha1.c +0 -362
  91. data/ext/iodine/fio_sha1.h +0 -107
  92. data/ext/iodine/fio_sha2.c +0 -842
  93. data/ext/iodine/fio_sha2.h +0 -169
  94. data/ext/iodine/pubsub.c +0 -867
  95. data/ext/iodine/pubsub.h +0 -221
  96. data/ext/iodine/sock.c +0 -1366
  97. data/ext/iodine/sock.h +0 -566
  98. data/ext/iodine/spnlock.inc +0 -111
@@ -3,6 +3,8 @@
3
3
 
4
4
  #include "ruby.h"
5
5
 
6
+ #include <stdint.h>
7
+
6
8
  extern struct IodineCaller_s {
7
9
  /** Calls a C function within the GVL (unprotected). */
8
10
  void *(*enterGVL)(void *(*func)(void *), void *arg);
@@ -1,13 +1,12 @@
1
1
  #include "iodine_connection.h"
2
2
 
3
- #include "facil.h"
4
- #include "fio_mem.h"
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 FIO_HASH_KEY_TYPE FIOBJ
45
- #define FIO_HASH_KEY_INVALID FIOBJ_INVALID
46
- #define FIO_HASH_KEY2UINT(key) fiobj_obj2hash((key))
47
- #define FIO_HASH_COMPARE_KEYS(k1, k2) (fiobj_iseq((k1), (k2)))
48
- #define FIO_HASH_KEY_ISINVALID(key) ((key) == FIOBJ_INVALID)
49
- #define FIO_HASH_KEY_COPY(key) (fiobj_dup(key))
50
- #define FIO_HASH_KEY_DESTROY(key) (fiobj_free((key)))
51
-
52
- #include "fio_hashmap.h"
53
-
54
- static inline VALUE iodine_sub_unsubscribe(fio_hash_s *store, FIOBJ channel) {
55
- pubsub_sub_pt sub = fio_hash_insert(store, channel, NULL);
56
- if (sub) {
57
- pubsub_unsubscribe(sub);
58
- return Qtrue;
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(fio_hash_s *store, pubsub_sub_pt sub) {
63
- FIOBJ channel = pubsub_sub_channel(sub); /* used for memory optimization */
64
- sub = fio_hash_insert(store, channel, sub);
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(fio_hash_s *store) {
70
- FIO_HASH_FOR_FREE(store, pos) {
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 spn_lock_i sub_lock = SPN_LOCK_INIT;
78
- static fio_hash_s sub_global = FIO_HASH_INIT;
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
- fio_hash_s subscriptions;
88
- spn_lock_i lock;
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 (spn_sub(&data->ref, 1))
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 = FIO_HASH_INIT,
146
- .lock = SPN_LOCK_INIT,
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 || sock_isclosed(c->info.uuid)) {
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, RSTRING_PTR(data), RSTRING_LEN(data),
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 = {.data = RSTRING_PTR(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
- size_t len = RSTRING_LEN(data);
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 && !sock_isclosed(c->info.uuid)) {
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
- sock_close(c->info.uuid);
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 && !sock_isclosed(c->info.uuid)) {
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 || sock_isclosed(c->info.uuid)) {
246
+ if (!c || fio_is_closed(c->info.uuid)) {
265
247
  return INT2NUM(-1);
266
248
  }
267
- return SIZET2NUM((sock_pending(c->info.uuid)));
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 && !sock_isclosed(c->info.uuid)) {
297
- size_t tout = (size_t)facil_get_timeout(c->info.uuid);
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 && !sock_isclosed(c->info.uuid)) {
317
- facil_set_timeout(c->info.uuid, (uint8_t)tout);
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
- pubsub_message_s *msg = msg_;
341
- fio_cstr_s tmp;
322
+ fio_msg_s *msg = msg_;
342
323
  VALUE args[2];
343
- tmp = fiobj_obj2cstr(msg->channel);
344
- args[0] = rb_str_new(tmp.data, tmp.len);
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(pubsub_message_s *msg) {
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
- sock_isclosed(data->info.uuid))
338
+ fio_is_closed(data->info.uuid))
360
339
  return;
361
340
  switch (data->info.type) {
362
341
  case IODINE_CONNECTION_WEBSOCKET: {
363
- fio_cstr_s str = fiobj_obj2cstr(msg->message);
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 = fiobj_obj2cstr(msg->message));
346
+ http_sse_write(data->info.arg, .data = msg->msg);
369
347
  return;
370
348
  default:
371
- fiobj_send_free(data->info.uuid, fiobj_dup(msg->message));
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 = 1;
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
- spn_add(&c->ref, 1);
508
+ fio_atomic_add(&c->ref, 1);
531
509
  }
532
510
 
533
- FIOBJ channel =
534
- fiobj_str_new(RSTRING_PTR(args.channel), RSTRING_LEN(args.channel));
535
- pubsub_sub_pt sub =
536
- pubsub_subscribe(.channel = channel, .on_message = iodine_on_pubsub,
537
- .on_unsubscribe = iodine_on_unsubscribe, .udata1 = c,
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
- spn_lock(&c->lock);
517
+ fio_lock(&c->lock);
543
518
  if (c->info.uuid == -1) {
544
- pubsub_unsubscribe(sub);
545
- spn_unlock(&c->lock);
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
- spn_unlock(&c->lock);
525
+ fio_unlock(&c->lock);
551
526
  } else {
552
- spn_lock(&sub_lock);
527
+ fio_lock(&sub_lock);
553
528
  iodine_sub_add(&sub_global, sub);
554
- spn_unlock(&sub_lock);
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
- spn_lock(&sub_lock);
579
- ret = iodine_sub_unsubscribe(&sub_global, channel);
580
- spn_unlock(&sub_lock);
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 subscribe a closed connection. */
558
+ return Qnil; /* cannot unsubscribe a closed connection. */
585
559
  }
586
- spn_lock(&sub_lock);
587
- ret = iodine_sub_unsubscribe(&sub_global, channel);
588
- spn_unlock(&sub_lock);
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 pubsub_engine_s *engine = NULL;
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 = PUBSUB_PROCESS_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
- FIOBJ ch = fiobj_str_new(RSTRING_PTR(rb_ch), RSTRING_LEN(rb_ch));
664
- FIOBJ msg = fiobj_str_new(RSTRING_PTR(rb_msg), RSTRING_LEN(rb_msg));
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 = FIO_HASH_INIT,
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 = SPN_LOCK_INIT,
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
- spn_lock(&data->lock);
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
- spn_unlock(&data->lock);
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);
@@ -5,8 +5,8 @@
5
5
  #include <stdint.h>
6
6
  // clang-format on
7
7
 
8
- #include "facil.h"
9
- #include <spnlock.inc>
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 spn_lock_i sock_io_thread = 0;
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
- sock_flush_all();
29
- tm = (struct timespec){.tv_nsec = 0, .tv_sec = 1};
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_, void *b_) {
35
- if (!spn_trylock(&sock_io_thread)) {
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 (spn_unlock(&sock_io_thread)) {
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
- spn_lock_i lock;
60
+ fio_lock_i lock;
58
61
  };
59
62
 
60
63
  /* used for GVL signalling */
61
- void call_async_signal(void *pool) { defer_pool_stop((pool_pt)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
- spn_unlock(&old_args->lock);
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
- defer(iodine_start_io_thread, NULL, NULL);
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 *defer_new_thread(void *(*thread_func)(void *), void *arg) {
125
+ void *fio_thread_new(void *(*thread_func)(void *), void *arg) {
120
126
  struct CreateThreadArgs data = (struct CreateThreadArgs){
121
- .thread_func = thread_func, .arg = arg, .lock = SPN_LOCK_INIT,
127
+ .thread_func = thread_func,
128
+ .arg = arg,
129
+ .lock = FIO_LOCK_INIT,
122
130
  };
123
- spn_lock(&data.lock);
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
- spn_lock(&data.lock);
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 defer_join_thread(void *thr) {
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 defer_free_thread(void *thr) { IodineStore.remove((VALUE)thr); }
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 facil_fork(void) {
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
- defer(iodine_defer_performe_once, (void *)block, NULL);
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 (facil_run_every(milli, 1, iodine_defer_run_timer, (void *)block,
225
- (void (*)(void *))IodineStore.remove) == -1) {
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 (facil_run_every(milli, repeat, iodine_defer_run_timer, (void *)block,
269
- (void (*)(void *))IodineStore.remove) == -1) {
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 spn_lock_i iodine_before_fork_lock = SPN_LOCK_INIT;
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 spn_lock_i iodine_after_fork_lock = SPN_LOCK_INIT;
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 spn_lock_i iodine_on_shutdown_lock = SPN_LOCK_INIT;
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
- spn_lock(&iodine_before_fork_lock);
303
+ fio_lock(&iodine_before_fork_lock);
298
304
  fio_ls_push(&iodine_before_fork_list, (void *)block);
299
- spn_unlock(&iodine_before_fork_lock);
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
- spn_lock(&iodine_after_fork_lock);
318
+ fio_lock(&iodine_after_fork_lock);
313
319
  fio_ls_push(&iodine_after_fork_list, (void *)block);
314
- spn_unlock(&iodine_after_fork_lock);
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
- spn_lock(&iodine_on_shutdown_lock);
334
+ fio_lock(&iodine_on_shutdown_lock);
329
335
  fio_ls_push(&iodine_on_shutdown_list, (void *)block);
330
- spn_unlock(&iodine_on_shutdown_lock);
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
- spn_lock_i *lock =
344
+ fio_lock_i *lock =
339
345
  before ? &iodine_before_fork_lock : &iodine_after_fork_lock;
340
- spn_lock(lock);
346
+ fio_lock(lock);
341
347
  FIO_LS_FOR(ls, pos) { IodineCaller.call((VALUE)(pos->obj), call_id); }
342
- spn_unlock(lock);
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
- spn_lock(&iodine_on_shutdown_lock);
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
- spn_unlock(&iodine_on_shutdown_lock);
362
+ fio_unlock(&iodine_on_shutdown_lock);
356
363
  /* clear away forking Procs */
357
- spn_lock(&iodine_before_fork_lock);
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
- spn_unlock(&iodine_before_fork_lock);
368
+ fio_unlock(&iodine_before_fork_lock);
362
369
 
363
- spn_lock(&iodine_after_fork_lock);
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
- spn_unlock(&iodine_after_fork_lock);
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
- defer(iodine_start_io_thread, NULL, NULL);
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
  }