iodine 0.4.5 → 0.4.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9f2f657fb4dfe53dba0db85aa2b84685287e0d1e
4
- data.tar.gz: '04085f50a4e1dcb50f960ea32a62717aed58b77c'
3
+ metadata.gz: d9f26da78f47f0d2d44534b5a0930862ac5c1092
4
+ data.tar.gz: 13b1d9adfa9e1df5f4544448ec551f879c6a32ac
5
5
  SHA512:
6
- metadata.gz: e464440c9fdaf6dba8ca6ae60e7d29d7d90cd6a3a31557573b558296ded54b83d373542777697e0b41cdde863d6131b73bbd8a9da9ca7d9f1b8a6a738ff66dc8
7
- data.tar.gz: a2a1e275c0754427e4f6efce6e1111976d9fb87a1c4710dd2be5d46627f3ee6476de8b7fa82e134a039ce50454bd981ba36aa96bd76dc69a9d8ba36852648af1
6
+ metadata.gz: '0381cd3d98e09b440636e7d4fd53a60139d7673b9595a2b7c9e2c6050d593f4920294496b462cf8661cd7cb3af464077664a78d6ba7afa27143b73bc16087678'
7
+ data.tar.gz: bb0f81ea6a19da939cf733a3a934c7d2396b9bc980abdff4331fb0c2e03c65a96918341df0ff41fb50e5379de758fa75e4df31e0f8db15b3d3b41bd38e5fcdb6
data/CHANGELOG.md CHANGED
@@ -6,6 +6,12 @@ Please notice that this change log contains changes for upcoming releases as wel
6
6
 
7
7
  ## Changes:
8
8
 
9
+ #### Change log v.0.4.6
10
+
11
+ **Update**: Now using `facil.io` v.0.5.2.
12
+
13
+ **Fix**: (from `facil.io`) fix `SIGTERM` handling, make sure sibling processes exit when a sibling dies.
14
+
9
15
  #### Change log v.0.4.5
10
16
 
11
17
  **Fix**: fix static file service for `X-Sendfile` as well as static error file fallback pages (404.html etc').
data/ext/iodine/defer.c CHANGED
@@ -30,24 +30,33 @@ Compile time settings
30
30
  Data Structures
31
31
  ***************************************************************************** */
32
32
 
33
+ /* task node data */
33
34
  typedef struct {
34
35
  void (*func)(void *, void *);
35
36
  void *arg1;
36
37
  void *arg2;
37
38
  } task_s;
38
39
 
40
+ /* a single linked list for tasks */
39
41
  typedef struct task_node_s {
40
42
  task_s task;
41
43
  struct task_node_s *next;
42
44
  } task_node_s;
43
45
 
46
+ /* static memory allocation for a task node buffer */
44
47
  static task_node_s tasks_buffer[DEFER_QUEUE_BUFFER];
45
48
 
49
+ /* the state machine - this holds all the data about the task queue and pool */
46
50
  static struct {
51
+ /* the next task to be performed */
47
52
  task_node_s *first;
53
+ /* a pointer to the linked list's tail, where the next task will be stored */
48
54
  task_node_s **last;
55
+ /* a linked list for task nodes (staticly allocated) */
49
56
  task_node_s *pool;
57
+ /* a lock for the state machine, used for multi-threading support */
50
58
  spn_lock_i lock;
59
+ /* a flag indicating whether the task pool was initialized */
51
60
  unsigned char initialized;
52
61
  } deferred = {.first = NULL,
53
62
  .last = &deferred.first,
@@ -61,9 +70,11 @@ API
61
70
 
62
71
  /** Defer an execution of a function for later. */
63
72
  int defer(void (*func)(void *, void *), void *arg1, void *arg2) {
73
+ /* must have a task to defer */
64
74
  if (!func)
65
75
  goto call_error;
66
76
  task_node_s *task;
77
+ /* lock the state machine, to grab/create a task and place it at the tail */
67
78
  spn_lock(&deferred.lock);
68
79
  if (deferred.pool) {
69
80
  task = deferred.pool;
@@ -74,6 +85,7 @@ int defer(void (*func)(void *, void *), void *arg1, void *arg2) {
74
85
  goto error;
75
86
  } else
76
87
  goto initialize;
88
+
77
89
  schedule:
78
90
  *deferred.last = task;
79
91
  deferred.last = &task->next;
@@ -83,13 +95,18 @@ schedule:
83
95
  task->next = NULL;
84
96
  spn_unlock(&deferred.lock);
85
97
  return 0;
98
+
86
99
  error:
87
100
  spn_unlock(&deferred.lock);
88
101
  perror("ERROR CRITICAL: defer can't allocate task");
89
102
  kill(0, SIGINT), exit(errno);
103
+
90
104
  call_error:
91
105
  return -1;
106
+
92
107
  initialize:
108
+ /* initialize the task pool using all the items in the static buffer */
109
+ /* also assign `task` one of the tasks from the pool and schedule the task */
93
110
  deferred.initialized = 1;
94
111
  task = tasks_buffer;
95
112
  deferred.pool = tasks_buffer + 1;
@@ -105,7 +122,7 @@ void defer_perform(void) {
105
122
  task_node_s *tmp;
106
123
  task_s task;
107
124
  restart:
108
- spn_lock(&deferred.lock);
125
+ spn_lock(&deferred.lock); /* remember never to perform tasks within a lock! */
109
126
  tmp = deferred.first;
110
127
  if (tmp) {
111
128
  deferred.first = tmp->next;
@@ -119,7 +136,9 @@ restart:
119
136
  free(tmp);
120
137
  }
121
138
  spn_unlock(&deferred.lock);
139
+ /* perform the task outside the lock. */
122
140
  task.func(task.arg1, task.arg2);
141
+ /* I used `goto` to optimize assembly instruction flow. maybe it helps. */
123
142
  goto restart;
124
143
  }
125
144
  spn_unlock(&deferred.lock);
@@ -136,6 +155,8 @@ Thread Pool Support
136
155
  defined(DEBUG)
137
156
  #include <pthread.h>
138
157
 
158
+ /* `weak` functions can be overloaded to change the thread implementation. */
159
+
139
160
  #pragma weak defer_new_thread
140
161
  void *defer_new_thread(void *(*thread_func)(void *), pool_pt arg) {
141
162
  pthread_t *thread = malloc(sizeof(*thread));
@@ -161,7 +182,7 @@ void defer_thread_throttle(unsigned long microsec) {
161
182
  throttle_thread(microsec);
162
183
  }
163
184
 
164
- #else /* No pthreads... BYO thread implementation. */
185
+ #else /* No pthreads... BYO thread implementation. This one simply fails. */
165
186
 
166
187
  #pragma weak defer_new_thread
167
188
  void *defer_new_thread(void *(*thread_func)(void *), void *arg) {
@@ -186,13 +207,17 @@ struct defer_pool {
186
207
  void *threads[];
187
208
  };
188
209
 
210
+ /* a thread's cycle. This is what a worker thread does... repeatedly. */
189
211
  static void *defer_worker_thread(void *pool_) {
190
212
  volatile pool_pt pool = pool_;
191
213
  signal(SIGPIPE, SIG_IGN);
214
+ /* the throttle replaces conditional variables for better performance */
192
215
  size_t throttle = (pool->count) * DEFER_THROTTLE;
193
216
  if (!throttle || throttle > 1572864UL)
194
217
  throttle = 1572864UL;
218
+ /* perform any available tasks */
195
219
  defer_perform();
220
+ /* as long as the flag is true, wait for and perform tasks. */
196
221
  do {
197
222
  throttle_thread(throttle);
198
223
  defer_perform();
@@ -200,10 +225,13 @@ static void *defer_worker_thread(void *pool_) {
200
225
  return NULL;
201
226
  }
202
227
 
228
+ /** Signals a running thread pool to stop. Returns immediately. */
203
229
  void defer_pool_stop(pool_pt pool) { pool->flag = 0; }
204
230
 
231
+ /** Returns TRUE (1) if the pool is hadn't been signaled to finish up. */
205
232
  int defer_pool_is_active(pool_pt pool) { return pool->flag; }
206
233
 
234
+ /** Waits for a running thread pool, joining threads and finishing all tasks. */
207
235
  void defer_pool_wait(pool_pt pool) {
208
236
  while (pool->count) {
209
237
  pool->count--;
@@ -211,6 +239,7 @@ void defer_pool_wait(pool_pt pool) {
211
239
  }
212
240
  }
213
241
 
242
+ /** The logic behind `defer_pool_start`. */
214
243
  static inline pool_pt defer_pool_initialize(unsigned int thread_count,
215
244
  pool_pt pool) {
216
245
  pool->flag = 1;
@@ -226,6 +255,7 @@ static inline pool_pt defer_pool_initialize(unsigned int thread_count,
226
255
  return NULL;
227
256
  }
228
257
 
258
+ /** Starts a thread pool that will run deferred tasks in the background. */
229
259
  pool_pt defer_pool_start(unsigned int thread_count) {
230
260
  if (thread_count == 0)
231
261
  return NULL;
@@ -239,22 +269,23 @@ pool_pt defer_pool_start(unsigned int thread_count) {
239
269
  Child Process support (`fork`)
240
270
  ***************************************************************************** */
241
271
 
272
+ /* forked `defer` workers use a global thread pool object. */
242
273
  static pool_pt forked_pool;
243
274
 
275
+ /* handles the SIGINT and SIGTERM signals by shutting down workers */
244
276
  static void sig_int_handler(int sig) {
245
- if (sig != SIGINT)
277
+ if (sig != SIGINT && sig != SIGTERM)
246
278
  return;
247
279
  if (!forked_pool)
248
280
  return;
249
281
  defer_pool_stop(forked_pool);
250
282
  }
251
283
 
252
- /* *
284
+ /*
253
285
  Zombie Reaping
254
286
  With thanks to Dr Graham D Shaw.
255
287
  http://www.microhowto.info/howto/reap_zombie_processes_using_a_sigchld_handler.html
256
288
  */
257
-
258
289
  void reap_child_handler(int sig) {
259
290
  (void)(sig);
260
291
  int old_errno = errno;
@@ -263,6 +294,7 @@ void reap_child_handler(int sig) {
263
294
  errno = old_errno;
264
295
  }
265
296
 
297
+ /* initializes zombie reaping for the process */
266
298
  inline static void reap_children(void) {
267
299
  struct sigaction sa;
268
300
  sa.sa_handler = reap_child_handler;
@@ -274,7 +306,9 @@ inline static void reap_children(void) {
274
306
  }
275
307
  }
276
308
 
309
+ /* a global process identifier (0 == root) */
277
310
  static int defer_fork_pid_id = 0;
311
+
278
312
  /**
279
313
  * Forks the process, starts up a thread pool and waits for all tasks to run.
280
314
  * All existing tasks will run in all processes (multiple times).
@@ -287,8 +321,12 @@ int defer_perform_in_fork(unsigned int process_count,
287
321
  if (forked_pool)
288
322
  return -1; /* we're already running inside an active `fork` */
289
323
 
324
+ /* we use a placeholder while initializing the forked thread pool, so calls to
325
+ * `defer_fork_is_active` don't fail.
326
+ */
290
327
  static struct defer_pool pool_placeholder = {.count = 1, .flag = 1};
291
328
 
329
+ /* setup signal handling */
292
330
  struct sigaction act, old, old_term, old_pipe;
293
331
  pid_t *pids = NULL;
294
332
  int ret = 0;
@@ -302,20 +340,26 @@ int defer_perform_in_fork(unsigned int process_count,
302
340
  perror("couldn't set signal handler");
303
341
  goto finish;
304
342
  };
343
+
305
344
  if (sigaction(SIGTERM, &act, &old_term)) {
306
345
  perror("couldn't set signal handler");
307
346
  goto finish;
308
347
  };
348
+
309
349
  act.sa_handler = SIG_IGN;
310
350
  if (sigaction(SIGPIPE, &act, &old_pipe)) {
311
351
  perror("couldn't set signal handler");
312
352
  goto finish;
313
353
  };
354
+
355
+ /* setup zomie reaping */
314
356
  reap_children();
315
357
 
316
358
  if (!process_count)
317
359
  process_count = 1;
318
360
  --process_count;
361
+
362
+ /* for `process_count == 0` nothing happens */
319
363
  pids = calloc(process_count, sizeof(*pids));
320
364
  if (process_count && !pids)
321
365
  goto finish;
@@ -334,12 +378,16 @@ int defer_perform_in_fork(unsigned int process_count,
334
378
  goto finish;
335
379
  }
336
380
  }
381
+
337
382
  pids_count++;
338
383
  forked_pool = &pool_placeholder;
339
384
  forked_pool = defer_pool_start(thread_count);
385
+
340
386
  defer_pool_wait(forked_pool);
341
387
  forked_pool = NULL;
388
+
342
389
  defer_perform();
390
+
343
391
  finish:
344
392
  if (pids) {
345
393
  for (size_t j = 0; j < pids_count; j++) {
data/ext/iodine/facil.c CHANGED
@@ -326,6 +326,7 @@ static void listener_ping(intptr_t uuid, protocol_s *plistener) {
326
326
  (void)plistener;
327
327
  }
328
328
 
329
+ /* called asynchronously after a new connection was opened */
329
330
  static void listener_deferred_on_open(void *uuid_, void *srv_uuid_) {
330
331
  intptr_t uuid = (intptr_t)uuid_;
331
332
  intptr_t srv_uuid = (intptr_t)srv_uuid_;
@@ -468,6 +469,7 @@ struct ConnectProtocol {
468
469
  int opened;
469
470
  };
470
471
 
472
+ /* The first `ready` signal is fired when a connection was established */
471
473
  static void connector_on_ready(intptr_t uuid, protocol_s *_connector) {
472
474
  struct ConnectProtocol *connector = (void *)_connector;
473
475
  // fprintf(stderr, "connector_on_ready called\n");
@@ -486,11 +488,13 @@ error:
486
488
  sock_close(uuid);
487
489
  }
488
490
 
491
+ /* If data events reach this protocol, delay their execution. */
489
492
  static void connector_on_data(intptr_t uuid, protocol_s *connector) {
490
493
  (void)connector;
491
- defer(deferred_on_data, (void *)uuid, NULL);
494
+ facil_force_event(uuid, FIO_EVENT_ON_DATA);
492
495
  }
493
496
 
497
+ /* Failed to connect */
494
498
  static void connector_on_close(intptr_t uuid, protocol_s *pconnector) {
495
499
  struct ConnectProtocol *connector = (void *)pconnector;
496
500
  if (connector->opened == 0 && connector->on_fail)
@@ -521,11 +525,12 @@ intptr_t facil_connect(struct facil_connect_args opt) {
521
525
  .opened = 0,
522
526
  };
523
527
  intptr_t uuid = connector->uuid = sock_connect(opt.address, opt.port);
528
+ /* check for errors, always invoke the on_fail if required */
524
529
  if (uuid == -1)
525
530
  goto error;
526
531
  if (facil_attach(uuid, &connector->protocol) == -1) {
527
532
  sock_close(uuid);
528
- return -1;
533
+ goto error;
529
534
  }
530
535
  return uuid;
531
536
  error:
@@ -710,6 +715,22 @@ static void facil_cluster_on_close(intptr_t uuid, protocol_s *pr_) {
710
715
  (void)uuid;
711
716
  }
712
717
 
718
+ /* React when a sibling process closes / crashes */
719
+ static void facil_cluster_on_sibling_close(intptr_t uuid, protocol_s *pr_) {
720
+ if (facil_cluster_data.pipes[defer_fork_pid()].in == uuid)
721
+ return;
722
+ if (defer_fork_is_active()) {
723
+ kill(getpid(), SIGINT);
724
+ #if DEBUG
725
+ fprintf(stderr,
726
+ "* Sibling death detected, signaling self exit process %d\n",
727
+ getpid());
728
+ #endif
729
+ }
730
+ (void)uuid;
731
+ (void)pr_;
732
+ }
733
+
713
734
  /* cluster protocol on_data callback */
714
735
  static void facil_cluster_on_data(intptr_t uuid, protocol_s *pr_) {
715
736
  struct facil_cluster_protocol *pr = (struct facil_cluster_protocol *)pr_;
@@ -755,12 +776,22 @@ static void facil_cluster_register(void *arg1, void *arg2) {
755
776
  (void)arg2;
756
777
  if (facil_cluster_data.count < 2)
757
778
  return;
758
- // for (size_t i = 0; i < facil_cluster_data.count; i++) {
759
- // if (i == (size_t)defer_fork_pid())
760
- // continue;
761
- // sock_close(facil_cluster_data.pipes[i].in);
762
- // }
763
- // sock_close(facil_cluster_data.pipes[defer_fork_pid()].out);
779
+
780
+ /* used to watch for sibling crashes and prevent other events from firing */
781
+ static protocol_s sentinel_protocol = {
782
+ .service = NULL,
783
+ .ping = listener_ping,
784
+ .on_close = facil_cluster_on_sibling_close,
785
+ };
786
+ /* close what we don't need and watch the connections we do need */
787
+ for (size_t i = 0; i < facil_cluster_data.count; i++) {
788
+ if (i == (size_t)defer_fork_pid())
789
+ continue;
790
+ sock_close(facil_cluster_data.pipes[i].in);
791
+ facil_attach(facil_cluster_data.pipes[i].out, &sentinel_protocol);
792
+ }
793
+ sock_close(facil_cluster_data.pipes[defer_fork_pid()].out);
794
+
764
795
  struct facil_cluster_protocol *pr = malloc(sizeof(*pr));
765
796
  if (!pr)
766
797
  perror("ERROR: (critical) cannot allocate memory for cluster."),
@@ -787,7 +818,10 @@ static void facil_cluster_init(uint16_t count) {
787
818
  if (!facil_cluster_data.pipes)
788
819
  goto error;
789
820
 
790
- static protocol_s stub_protocol = {.service = NULL, .ping = listener_ping};
821
+ /* used to prevent any events from firing */
822
+ static protocol_s stub_protocol = {
823
+ .service = NULL, .ping = listener_ping,
824
+ };
791
825
  stub_protocol.service = facil_cluster_protocol_id;
792
826
 
793
827
  facil_cluster_data.count = count;
@@ -799,8 +833,8 @@ static void facil_cluster_init(uint16_t count) {
799
833
  sock_set_non_block(p_tmp[0]);
800
834
  sock_set_non_block(p_tmp[1]);
801
835
  facil_cluster_data.pipes[i].in = sock_open(p_tmp[0]);
802
- facil_cluster_data.pipes[i].out = sock_open(p_tmp[1]);
803
836
  facil_attach(facil_cluster_data.pipes[i].in, &stub_protocol);
837
+ facil_cluster_data.pipes[i].out = sock_open(p_tmp[1]);
804
838
  facil_attach(facil_cluster_data.pipes[i].out, &stub_protocol);
805
839
  }
806
840
  defer(facil_cluster_register, NULL, NULL);
data/ext/iodine/facil.h CHANGED
@@ -8,14 +8,10 @@ Feel free to copy, use and enjoy according to the license provided.
8
8
  /**
9
9
  "facil.h" is the main header for the facil.io server platform.
10
10
  */
11
- #ifdef __cplusplus
12
- extern "C" {
13
- #endif
14
-
15
11
  #define H_FACIL_H
16
12
  #define FACIL_VERSION_MAJOR 0
17
13
  #define FACIL_VERSION_MINOR 5
18
- #define FACIL_VERSION_PATCH 0
14
+ #define FACIL_VERSION_PATCH 2
19
15
 
20
16
  #ifndef FACIL_PRINT_STATE
21
17
  /**
@@ -30,6 +26,11 @@ Required facil libraries
30
26
  #include "defer.h"
31
27
  #include "sock.h"
32
28
 
29
+ /* support C++ */
30
+ #ifdef __cplusplus
31
+ extern "C" {
32
+ #endif
33
+
33
34
  /* *****************************************************************************
34
35
  Core object types
35
36
  ***************************************************************************** */
@@ -21,6 +21,11 @@ the key "hello1" will cost only 272 bytes... brrr.
21
21
  #include <stdint.h>
22
22
  #include <stdlib.h>
23
23
 
24
+ /* support C++ */
25
+ #ifdef __cplusplus
26
+ extern "C" {
27
+ #endif
28
+
24
29
  typedef struct fio_dict_s {
25
30
  struct fio_dict_s *parent;
26
31
  struct fio_dict_s *trie[16];
@@ -87,4 +92,8 @@ int fio_glob_match(uint8_t *data, size_t data_len, uint8_t *pattern,
87
92
  (dict)->trie[12] || (dict)->trie[13] || (dict)->trie[14] || \
88
93
  (dict)->trie[15]))
89
94
 
95
+ #ifdef __cplusplus
96
+ } /* extern "C" */
97
+ #endif
98
+
90
99
  #endif
data/ext/iodine/http.h CHANGED
@@ -54,6 +54,11 @@ Hard Coded Settings
54
54
  #define HTTP_DEFAULT_BODY_LIMIT (1024 * 1024 * 50)
55
55
  #endif
56
56
 
57
+ /* support C++ */
58
+ #ifdef __cplusplus
59
+ extern "C" {
60
+ #endif
61
+
57
62
  /* *****************************************************************************
58
63
  HTTP Core API & data structure
59
64
  */
@@ -200,4 +205,8 @@ ssize_t http_decode_path_unsafe(char *dest, const char *url_data);
200
205
  */
201
206
  ssize_t http_decode_path(char *dest, const char *url_data, size_t length);
202
207
 
208
+ #ifdef __cplusplus
209
+ } /* extern "C" */
210
+ #endif
211
+
203
212
  #endif
@@ -10,6 +10,11 @@ typedef struct http_request_s http_request_s;
10
10
 
11
11
  #include "http.h"
12
12
 
13
+ /* support C++ */
14
+ #ifdef __cplusplus
15
+ extern "C" {
16
+ #endif
17
+
13
18
  struct http_request_s {
14
19
  /** the HTTP version, also controlls the `http_request_s` flavor. */
15
20
  enum HTTP_VERSION http_version;
@@ -90,4 +95,8 @@ http_header_s http_request_header_first(http_request_s *request);
90
95
  * Header itteration is NOT thread-safe. */
91
96
  http_header_s http_request_header_next(http_request_s *request);
92
97
 
98
+ #ifdef __cplusplus
99
+ } /* extern "C" */
100
+ #endif
101
+
93
102
  #endif /* H_HTTP_REQUEST_H */
@@ -10,6 +10,11 @@ Feel free to copy, use and enjoy according to the license provided.
10
10
  #include <stdio.h>
11
11
  #include <time.h>
12
12
 
13
+ /* support C++ */
14
+ #ifdef __cplusplus
15
+ extern "C" {
16
+ #endif
17
+
13
18
  typedef struct {
14
19
  /** The protocol version family (HTTP/1.1 / HTTP/2 etc'). */
15
20
  enum HTTP_VERSION http_version;
@@ -238,4 +243,8 @@ const char *http_response_ext2mime(const char *ext);
238
243
  /** Starts counting miliseconds for log results. */
239
244
  void http_response_log_start(http_response_s *);
240
245
 
246
+ #ifdef __cplusplus
247
+ } /* extern "C" */
248
+ #endif
249
+
241
250
  #endif
data/ext/iodine/pubsub.c CHANGED
@@ -266,8 +266,7 @@ const pubsub_engine_s PUBSUB_PROCESS_ENGINE_S = {
266
266
  };
267
267
  const pubsub_engine_s *PUBSUB_PROCESS_ENGINE = &PUBSUB_PROCESS_ENGINE_S;
268
268
 
269
- pubsub_engine_s *PUBSUB_DEFAULT_ENGINE =
270
- (pubsub_engine_s *)&PUBSUB_CLUSTER_ENGINE_S;
269
+ const pubsub_engine_s *PUBSUB_DEFAULT_ENGINE = &PUBSUB_CLUSTER_ENGINE_S;
271
270
 
272
271
  /* *****************************************************************************
273
272
  External Engine Bridge
data/ext/iodine/pubsub.h CHANGED
@@ -20,6 +20,11 @@ between all of an application's processes, enhancing overall performance.
20
20
  #define H_FACIL_PUBSUB_H
21
21
  #include "facil.h"
22
22
 
23
+ /* support C++ */
24
+ #ifdef __cplusplus
25
+ extern "C" {
26
+ #endif
27
+
23
28
  #ifndef FIO_PUBBSUB_MAX_CHANNEL_LEN
24
29
  #define FIO_PUBBSUB_MAX_CHANNEL_LEN 1024
25
30
  #endif
@@ -191,7 +196,7 @@ extern const pubsub_engine_s *PUBSUB_CLUSTER_ENGINE;
191
196
  extern const pubsub_engine_s *PUBSUB_PROCESS_ENGINE;
192
197
 
193
198
  /** Allows process wide changes to the default Pub/Sub Engine. */
194
- extern pubsub_engine_s *PUBSUB_DEFAULT_ENGINE;
199
+ extern const pubsub_engine_s *PUBSUB_DEFAULT_ENGINE;
195
200
 
196
201
  /**
197
202
  * The function used by engines to distribute received messages.
@@ -212,4 +217,8 @@ void pubsub_engine_distribute(pubsub_message_s msg);
212
217
  */
213
218
  void pubsub_engine_resubscribe(pubsub_engine_s *eng);
214
219
 
220
+ #ifdef __cplusplus
221
+ } /* extern "C" */
222
+ #endif
223
+
215
224
  #endif /* H_FACIL_PUBSUB_H */
@@ -10,6 +10,11 @@ Feel free to copy, use and enjoy in accordance with to the license(s).
10
10
  #include "facil.h"
11
11
  #include "resp.h"
12
12
 
13
+ /* support C++ */
14
+ #ifdef __cplusplus
15
+ extern "C" {
16
+ #endif
17
+
13
18
  /* *****************************************************************************
14
19
  Connectivity
15
20
  ***************************************************************************** */
@@ -74,4 +79,8 @@ protocol_s *redis_create_server_protocol(intptr_t uuid, void *settings);
74
79
  */
75
80
  void redis_protocol_cleanup(intptr_t uuid, void *settings);
76
81
 
82
+ #ifdef __cplusplus
83
+ } /* extern "C" */
84
+ #endif
85
+
77
86
  #endif
@@ -346,7 +346,7 @@ See the {pubsub.h} file for documentation about engines.
346
346
 
347
347
  function names speak for themselves ;-)
348
348
  */
349
- void redis_engine_destroy(pubsub_engine_s *engine) {
349
+ void redis_engine_destroy(const pubsub_engine_s *engine) {
350
350
  redis_engine_s *r = (redis_engine_s *)engine;
351
351
 
352
352
  spn_lock(&r->lock);
@@ -17,6 +17,11 @@ subscription or publication... it will simply try until successful.
17
17
  #include "pubsub.h"
18
18
  #include "resp.h"
19
19
 
20
+ /* support C++ */
21
+ #ifdef __cplusplus
22
+ extern "C" {
23
+ #endif
24
+
20
25
  /** possible arguments for the `redis_engine_create` function call */
21
26
  struct redis_engine_create_args {
22
27
  /** Redis server's address */
@@ -64,5 +69,10 @@ See the {pubsub.h} file for documentation about engines.
64
69
 
65
70
  function names speak for themselves ;-)
66
71
  */
67
- void redis_engine_destroy(pubsub_engine_s *engine);
72
+ void redis_engine_destroy(const pubsub_engine_s *engine);
73
+
74
+ #ifdef __cplusplus
75
+ } /* extern "C" */
76
+ #endif
77
+
68
78
  #endif
data/ext/iodine/resp.h CHANGED
@@ -14,6 +14,11 @@ This is a neive implementation of the RESP protocol for Redis.
14
14
  #include <stdint.h>
15
15
  #include <stdlib.h>
16
16
 
17
+ /* support C++ */
18
+ #ifdef __cplusplus
19
+ extern "C" {
20
+ #endif
21
+
17
22
  /** The RESP Parser Type */
18
23
  typedef struct resp_parser_s *resp_parser_pt;
19
24
 
@@ -250,4 +255,8 @@ void resp_enable_duplex_pubsub(resp_parser_pt parser);
250
255
  void resp_test(void);
251
256
  #endif
252
257
 
258
+ #ifdef __cplusplus
259
+ } /* extern "C" */
260
+ #endif
261
+
253
262
  #endif
@@ -9,6 +9,11 @@ Feel free to copy, use and enjoy according to the license provided.
9
9
 
10
10
  #include "http.h"
11
11
 
12
+ /* support C++ */
13
+ #ifdef __cplusplus
14
+ extern "C" {
15
+ #endif
16
+
12
17
  /* *****************************************************************************
13
18
  Upgrading from HTTP to Websockets
14
19
  ***************************************************************************** */
@@ -342,4 +347,8 @@ int websocket_write_each(struct websocket_write_each_args_s args);
342
347
  #define websocket_write_each(...) \
343
348
  websocket_write_each((struct websocket_write_each_args_s){__VA_ARGS__})
344
349
 
350
+ #ifdef __cplusplus
351
+ } /* extern "C" */
352
+ #endif
353
+
345
354
  #endif
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.4.5'.freeze
2
+ VERSION = '0.4.6'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iodine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-28 00:00:00.000000000 Z
11
+ date: 2017-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack