rbczmq 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. data/.gitignore +23 -0
  2. data/.travis.yml +19 -0
  3. data/Gemfile +5 -0
  4. data/Gemfile.lock +19 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +247 -0
  7. data/Rakefile +67 -0
  8. data/examples/loop.rb +109 -0
  9. data/examples/poller.rb +37 -0
  10. data/examples/pub_sub.rb +101 -0
  11. data/examples/push_pull.rb +104 -0
  12. data/examples/req_rep.rb +100 -0
  13. data/ext/czmq.tar.gz +0 -0
  14. data/ext/rbczmq/context.c +280 -0
  15. data/ext/rbczmq/context.h +26 -0
  16. data/ext/rbczmq/extconf.rb +138 -0
  17. data/ext/rbczmq/frame.c +401 -0
  18. data/ext/rbczmq/frame.h +24 -0
  19. data/ext/rbczmq/jruby.h +22 -0
  20. data/ext/rbczmq/loop.c +413 -0
  21. data/ext/rbczmq/loop.h +24 -0
  22. data/ext/rbczmq/message.c +620 -0
  23. data/ext/rbczmq/message.h +24 -0
  24. data/ext/rbczmq/poller.c +308 -0
  25. data/ext/rbczmq/poller.h +29 -0
  26. data/ext/rbczmq/pollitem.c +251 -0
  27. data/ext/rbczmq/pollitem.h +25 -0
  28. data/ext/rbczmq/rbczmq_ext.c +198 -0
  29. data/ext/rbczmq/rbczmq_ext.h +94 -0
  30. data/ext/rbczmq/rbczmq_prelude.h +22 -0
  31. data/ext/rbczmq/rubinius.h +24 -0
  32. data/ext/rbczmq/ruby18.h +43 -0
  33. data/ext/rbczmq/ruby19.h +15 -0
  34. data/ext/rbczmq/socket.c +1570 -0
  35. data/ext/rbczmq/socket.h +136 -0
  36. data/ext/rbczmq/timer.c +110 -0
  37. data/ext/rbczmq/timer.h +23 -0
  38. data/ext/zeromq.tar.gz +0 -0
  39. data/lib/rbczmq.rb +3 -0
  40. data/lib/zmq.rb +77 -0
  41. data/lib/zmq/context.rb +50 -0
  42. data/lib/zmq/default_handler.rb +16 -0
  43. data/lib/zmq/frame.rb +11 -0
  44. data/lib/zmq/handler.rb +76 -0
  45. data/lib/zmq/loop.rb +131 -0
  46. data/lib/zmq/message.rb +9 -0
  47. data/lib/zmq/poller.rb +22 -0
  48. data/lib/zmq/pollitem.rb +31 -0
  49. data/lib/zmq/socket.rb +125 -0
  50. data/lib/zmq/socket/dealer.rb +33 -0
  51. data/lib/zmq/socket/pair.rb +39 -0
  52. data/lib/zmq/socket/pub.rb +30 -0
  53. data/lib/zmq/socket/pull.rb +29 -0
  54. data/lib/zmq/socket/push.rb +32 -0
  55. data/lib/zmq/socket/rep.rb +37 -0
  56. data/lib/zmq/socket/req.rb +37 -0
  57. data/lib/zmq/socket/router.rb +38 -0
  58. data/lib/zmq/socket/sub.rb +27 -0
  59. data/lib/zmq/timer.rb +12 -0
  60. data/lib/zmq/version.rb +5 -0
  61. data/perf/pair.rb +7 -0
  62. data/perf/pair/local.rb +22 -0
  63. data/perf/pair/remote.rb +25 -0
  64. data/perf/pub_sub.rb +7 -0
  65. data/perf/pub_sub/local.rb +22 -0
  66. data/perf/pub_sub/remote.rb +25 -0
  67. data/perf/push_pull.rb +7 -0
  68. data/perf/push_pull/local.rb +21 -0
  69. data/perf/push_pull/remote.rb +25 -0
  70. data/perf/req_rep.rb +7 -0
  71. data/perf/req_rep/local.rb +35 -0
  72. data/perf/req_rep/remote.rb +28 -0
  73. data/perf/runner.rb +142 -0
  74. data/rbczmq.gemspec +22 -0
  75. data/test/helper.rb +21 -0
  76. data/test/socket/test_dealer_socket.rb +14 -0
  77. data/test/socket/test_pair_socket.rb +24 -0
  78. data/test/socket/test_pair_sockets.rb +74 -0
  79. data/test/socket/test_pub_socket.rb +17 -0
  80. data/test/socket/test_pub_sub_sockets.rb +87 -0
  81. data/test/socket/test_pull_socket.rb +17 -0
  82. data/test/socket/test_push_pull_sockets.rb +81 -0
  83. data/test/socket/test_push_socket.rb +17 -0
  84. data/test/socket/test_rep_socket.rb +25 -0
  85. data/test/socket/test_req_rep_sockets.rb +42 -0
  86. data/test/socket/test_req_socket.rb +27 -0
  87. data/test/socket/test_router_socket.rb +14 -0
  88. data/test/socket/test_routing.rb +66 -0
  89. data/test/socket/test_sub_socket.rb +17 -0
  90. data/test/test_context.rb +86 -0
  91. data/test/test_frame.rb +78 -0
  92. data/test/test_handler.rb +28 -0
  93. data/test/test_loop.rb +252 -0
  94. data/test/test_message.rb +201 -0
  95. data/test/test_poller.rb +154 -0
  96. data/test/test_pollitem.rb +78 -0
  97. data/test/test_socket.rb +403 -0
  98. data/test/test_threading.rb +34 -0
  99. data/test/test_timer.rb +37 -0
  100. data/test/test_zmq.rb +62 -0
  101. metadata +208 -0
@@ -0,0 +1,24 @@
1
+ #ifndef RBCZMQ_FRAME_H
2
+ #define RBCZMQ_FRAME_H
3
+
4
+ #define ZmqAssertFrame(obj) ZmqAssertType(obj, rb_cZmqFrame, "ZMQ::Frame")
5
+ #define ZmqGetFrame(obj) \
6
+ zframe_t *frame = NULL; \
7
+ ZmqAssertFrame(obj); \
8
+ Data_Get_Struct(obj, zframe_t, frame); \
9
+ if (!frame) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!"); \
10
+ if (!(st_lookup(frames_map, (st_data_t)frame, 0))) rb_raise(rb_eZmqError, "ZMQ::Frame instance %p has been destroyed by the ZMQ framework", (void *)obj);
11
+
12
+ #define ZmqRegisterFrame(fr) \
13
+ zframe_freefn((fr), rb_czmq_frame_freed); \
14
+ st_insert(frames_map, (st_data_t)(fr), (st_data_t)0);
15
+
16
+ void rb_czmq_free_frame(zframe_t *frame);
17
+ void rb_czmq_free_frame_gc(void *ptr);
18
+ void rb_czmq_frame_freed(zframe_t *frame);
19
+
20
+ VALUE rb_czmq_alloc_frame(zframe_t *frame);
21
+
22
+ void _init_rb_czmq_frame();
23
+
24
+ #endif
@@ -0,0 +1,22 @@
1
+ #ifndef RBCZMQ_JRUBY_H
2
+ #define RBCZMQ_JRUBY_H
3
+
4
+ #include "st.h"
5
+
6
+ /* XXX */
7
+ #define ZmqEncode(str) str
8
+ #ifndef THREAD_PASS
9
+ #define THREAD_PASS rb_thread_schedule();
10
+ #endif
11
+
12
+ #define TRAP_BEG
13
+ #define TRAP_END
14
+
15
+ #undef rb_errinfo
16
+ #define rb_errinfo() (rb_gv_get("$!"))
17
+
18
+ #define ZMQ_DEFAULT_SOCKET_TIMEOUT Qnil
19
+
20
+ #define HAVE_RB_THREAD_BLOCKING_REGION 1
21
+
22
+ #endif
data/ext/rbczmq/loop.c ADDED
@@ -0,0 +1,413 @@
1
+ #include <rbczmq_ext.h>
2
+
3
+ static VALUE intern_call;
4
+ static VALUE intern_readable;
5
+ static VALUE intern_writable;
6
+ static VALUE intern_error;
7
+
8
+ /*
9
+ * :nodoc:
10
+ * Wraps rb_funcall to support callbacks with or without callbacks.
11
+ *
12
+ */
13
+ static VALUE rb_czmq_callback0(VALUE *args)
14
+ {
15
+ return (NIL_P(args[2])) ? rb_funcall(args[0], args[1], 0) : rb_funcall(args[0], args[1], 1, args[2]);
16
+ }
17
+
18
+ /*
19
+ * :nodoc:
20
+ * Callback for when the reactor started. Invoked from a a oneshot timer that fires after 1ms and updates the running
21
+ * member on the loop struct.
22
+ *
23
+ */
24
+ ZMQ_NOINLINE static int rb_czmq_loop_started_callback(ZMQ_UNUSED zloop_t *loop, ZMQ_UNUSED zmq_pollitem_t *item, void *arg)
25
+ {
26
+ zmq_loop_wrapper *loop_wrapper = arg;
27
+ loop_wrapper->running = TRUE;
28
+ return 0;
29
+ }
30
+
31
+ /*
32
+ * :nodoc:
33
+ * Callback to signal / break the reactor loop. Triggered when we invoke ZMQ::Loop#stop. The -1 return will trickle down
34
+ * to libczmq and stop the event loop.
35
+ *
36
+ */
37
+ ZMQ_NOINLINE static int rb_czmq_loop_breaker_callback(ZMQ_UNUSED zloop_t *loop, ZMQ_UNUSED zmq_pollitem_t *item, void *arg)
38
+ {
39
+ zmq_loop_wrapper *loop_wrapper = arg;
40
+ loop_wrapper->running = FALSE;
41
+ return -1;
42
+ }
43
+
44
+ /*
45
+ * :nodoc:
46
+ * Wraps calls back into the Ruby VM with rb_protect and properly bubbles up an errors to the user.
47
+ *
48
+ */
49
+ ZMQ_NOINLINE static int rb_czmq_callback(zloop_t *loop, VALUE *args)
50
+ {
51
+ int status;
52
+ volatile VALUE ret;
53
+ status = 0;
54
+ ret = rb_protect((VALUE(*)(VALUE))rb_czmq_callback0, (VALUE)args, &status);
55
+ if (status) {
56
+ zloop_timer(loop, 1, 1, rb_czmq_loop_breaker_callback, (void *)args[0]);
57
+ if (NIL_P(rb_errinfo())) {
58
+ rb_jump_tag(status);
59
+ } else {
60
+ rb_funcall(args[0], intern_error, 1, rb_errinfo());
61
+ return 0;
62
+ }
63
+ } else if (ret == Qfalse) {
64
+ zloop_timer(loop, 1, 1, rb_czmq_loop_breaker_callback, (void *)args[0]);
65
+ return -1;
66
+ }
67
+ return 0;
68
+ }
69
+
70
+ /*
71
+ * :nodoc:
72
+ * Low level callback for when timers registered with the reactor fires. This calls back into the Ruby VM.
73
+ *
74
+ */
75
+ ZMQ_NOINLINE static int rb_czmq_loop_timer_callback(zloop_t *loop, ZMQ_UNUSED zmq_pollitem_t *item, void *cb)
76
+ {
77
+ int rc;
78
+ VALUE args[3];
79
+ ZmqGetTimer((VALUE)cb);
80
+ if (timer->cancelled == TRUE) {
81
+ zloop_timer_end(loop, (void *)cb);
82
+ return 0;
83
+ }
84
+ args[0] = (VALUE)cb;
85
+ args[1] = intern_call;
86
+ args[2] = Qnil;
87
+ rc = rb_czmq_callback(loop, args);
88
+ return rc;
89
+ }
90
+
91
+ /*
92
+ * :nodoc:
93
+ * Low level callback for handling socket activity. This calls back into the Ruby VM. We special case ZMQ_POLLERR
94
+ * by invoking the error callback on the handler registered for this socket.
95
+ *
96
+ */
97
+ ZMQ_NOINLINE static int rb_czmq_loop_pollitem_callback(zloop_t *loop, zmq_pollitem_t *item, void *arg)
98
+ {
99
+ int ret_r = 0;
100
+ int ret_w = 0;
101
+ int ret_e = 0;
102
+ VALUE args[3];
103
+ zmq_pollitem_wrapper *pollitem = (zmq_pollitem_wrapper *)arg;
104
+ args[0] = (VALUE)pollitem->handler;
105
+ args[2] = Qnil;
106
+ if (item->revents & ZMQ_POLLIN) {
107
+ args[1] = intern_readable;
108
+ ret_r = rb_czmq_callback(loop, args);
109
+ }
110
+ if (item->revents & ZMQ_POLLOUT) {
111
+ args[1] = intern_writable;
112
+ ret_w = rb_czmq_callback(loop, args);
113
+ }
114
+ if (item->revents & ZMQ_POLLERR) {
115
+ args[1] = intern_error;
116
+ args[2] = rb_exc_new2(rb_eZmqError, zmq_strerror(zmq_errno()));
117
+ ret_e = rb_czmq_callback(loop, args);
118
+ }
119
+ if (ret_r == -1 || ret_w == -1 || ret_e == -1) return -1;
120
+ return 0;
121
+ }
122
+
123
+ static void rb_czmq_loop_stop0(zmq_loop_wrapper *loop);
124
+
125
+ /*
126
+ * :nodoc:
127
+ * Free all resources for a reactor loop - invoked by the lower level ZMQ::Loop#destroy as well as the GC callback
128
+ *
129
+ */
130
+ static void rb_czmq_free_loop(zmq_loop_wrapper *loop)
131
+ {
132
+ rb_czmq_loop_stop0(loop);
133
+ zloop_destroy(&(loop->loop));
134
+ loop->loop = NULL;
135
+ loop->flags |= ZMQ_LOOP_DESTROYED;
136
+ }
137
+
138
+ /*
139
+ * :nodoc:
140
+ * GC free callback
141
+ *
142
+ */
143
+ static void rb_czmq_free_loop_gc(void *ptr)
144
+ {
145
+ zmq_loop_wrapper *loop = (zmq_loop_wrapper *)ptr;
146
+ if (loop) {
147
+ if (loop->loop != NULL && !(loop->flags & ZMQ_LOOP_DESTROYED)) rb_czmq_free_loop(loop);
148
+ xfree(loop);
149
+ }
150
+ }
151
+
152
+ /*
153
+ * call-seq:
154
+ * ZMQ::Loop.new => ZMQ::Loop
155
+ *
156
+ * Creates a new reactor instance. Several loops per process is supported for the lower level API.
157
+ *
158
+ * === Examples
159
+ * ZMQ::Loop.new => ZMQ::Loop
160
+ *
161
+ */
162
+
163
+ static VALUE rb_czmq_loop_new(VALUE loop)
164
+ {
165
+ zmq_loop_wrapper *lp = NULL;
166
+ errno = 0;
167
+ loop = Data_Make_Struct(rb_cZmqLoop, zmq_loop_wrapper, 0, rb_czmq_free_loop_gc, lp);
168
+ lp->loop = zloop_new();
169
+ ZmqAssertObjOnAlloc(lp->loop, lp);
170
+ lp->flags = 0;
171
+ lp->running = FALSE;
172
+ lp->verbose = FALSE;
173
+ rb_obj_call_init(loop, 0, NULL);
174
+ return loop;
175
+ }
176
+
177
+ /*
178
+ * call-seq:
179
+ * loop.start => Fixnum
180
+ *
181
+ * Creates a new reactor instance and blocks the caller until the process is interrupted, the context terminates or the
182
+ * loop's explicitly stopped via callback. Returns 0 if interrupted and -1 when stopped via a handler.
183
+ *
184
+ * === Examples
185
+ * loop = ZMQ::Loop.new => ZMQ::Loop
186
+ * loop.start => Fixnum
187
+ *
188
+ */
189
+
190
+ static VALUE rb_czmq_loop_start(VALUE obj)
191
+ {
192
+ int rc;
193
+ errno = 0;
194
+ ZmqGetLoop(obj);
195
+ THREAD_PASS;
196
+ zloop_timer(loop->loop, 1, 1, rb_czmq_loop_started_callback, loop);
197
+ rc = zloop_start(loop->loop);
198
+ if (rc > 0) rb_raise(rb_eZmqError, "internal event loop error!");
199
+ return INT2NUM(rc);
200
+ }
201
+
202
+ /*
203
+ * call-seq:
204
+ * loop.running? => boolean
205
+ *
206
+ * Predicate that returns true if the reactor is currently running.
207
+ *
208
+ * === Examples
209
+ * loop = ZMQ::Loop.new => ZMQ::Loop
210
+ * loop.running? => false
211
+ *
212
+ */
213
+
214
+ static VALUE rb_czmq_loop_running_p(VALUE obj)
215
+ {
216
+ ZmqGetLoop(obj);
217
+ return (loop->running == TRUE) ? Qtrue : Qfalse;
218
+ }
219
+
220
+ /*
221
+ * :nodoc:
222
+ * Registers a oneshot timer that'll fire after 1msec to signal a loop break.
223
+ *
224
+ */
225
+ static void rb_czmq_loop_stop0(zmq_loop_wrapper *loop)
226
+ {
227
+ zloop_timer(loop->loop, 1, 1, rb_czmq_loop_breaker_callback, loop);
228
+ }
229
+
230
+ /*
231
+ * call-seq:
232
+ * loop.stop => nil
233
+ *
234
+ * Stops the reactor loop. ZMQ::Loop#start will return a -1 status code as this can only be called via a handler.
235
+ *
236
+ * === Examples
237
+ * loop = ZMQ::Loop.new => ZMQ::Loop
238
+ * loop.add_timer(1){ loop.stop }
239
+ * loop.start => -1
240
+ *
241
+ */
242
+
243
+ static VALUE rb_czmq_loop_stop(VALUE obj)
244
+ {
245
+ ZmqGetLoop(obj);
246
+ if (loop->running == FALSE) rb_raise(rb_eZmqError, "event loop not running!");
247
+ rb_czmq_loop_stop0(loop);
248
+ return Qnil;
249
+ }
250
+
251
+ /*
252
+ * call-seq:
253
+ * loop.destroy => nil
254
+ *
255
+ * Explicitly destroys a reactor instance. Useful for manual memory management, otherwise the GC
256
+ * will take the same action if a message object is not reachable anymore on the next GC cycle. This is
257
+ * a lower level API.
258
+ *
259
+ * === Examples
260
+ * loop = ZMQ::Loop.new => ZMQ::Loop
261
+ * loop.destroy => nil
262
+ *
263
+ */
264
+
265
+ static VALUE rb_czmq_loop_destroy(VALUE obj)
266
+ {
267
+ ZmqGetLoop(obj);
268
+ rb_czmq_free_loop(loop);
269
+ return Qnil;
270
+ }
271
+
272
+ /*
273
+ * call-seq:
274
+ * loop.verbose = true => nil
275
+ *
276
+ * Logs reactor activity to stdout - useful for debugging, but can be quite noisy with lots of activity.
277
+ *
278
+ * === Examples
279
+ * loop = ZMQ::Loop.new => ZMQ::Loop
280
+ * loop.verbose = true => nil
281
+ *
282
+ */
283
+
284
+ static VALUE rb_czmq_loop_set_verbose(VALUE obj, VALUE level)
285
+ {
286
+ Bool vlevel;
287
+ ZmqGetLoop(obj);
288
+ vlevel = (level == Qtrue) ? TRUE : FALSE;
289
+ zloop_set_verbose(loop->loop, vlevel);
290
+ loop->verbose = vlevel;
291
+ return Qnil;
292
+ }
293
+
294
+ /*
295
+ * call-seq:
296
+ * loop.register(item) => true
297
+ *
298
+ * Registers a poll item with the reactor. Only ZMQ::POLLIN and ZMQ::POLLOUT events are supported.
299
+ *
300
+ * === Examples
301
+ * loop = ZMQ::Loop.new => ZMQ::Loop
302
+ * item = ZMQ::Pollitem.new(sock, ZMQ::POLLIN) => ZMQ::Pollitem
303
+ * loop.register(item) => true
304
+ *
305
+ */
306
+
307
+ static VALUE rb_czmq_loop_register(VALUE obj, VALUE pollable)
308
+ {
309
+ int rc;
310
+ errno = 0;
311
+ ZmqGetLoop(obj);
312
+ pollable = rb_czmq_pollitem_coerce(pollable);
313
+ ZmqGetPollitem(pollable);
314
+ rc = zloop_poller(loop->loop, pollitem->item, rb_czmq_loop_pollitem_callback, (void *)pollitem);
315
+ ZmqAssert(rc);
316
+ /* Let pollable be verbose if loop is verbose */
317
+ if (loop->verbose == TRUE) rb_czmq_pollitem_set_verbose(pollable, Qtrue);
318
+ return Qtrue;
319
+ }
320
+
321
+ /*
322
+ * call-seq:
323
+ * loop.remove(item) => nil
324
+ *
325
+ * Removes a previously registered poll item from the reactor loop.
326
+ *
327
+ * === Examples
328
+ * loop = ZMQ::Loop.new => ZMQ::Loop
329
+ * item = ZMQ::Pollitem.new(sock, ZMQ::POLLIN) => ZMQ::Pollitem
330
+ * loop.register(item) => true
331
+ * loop.remove(item) => nil
332
+ *
333
+ */
334
+
335
+ static VALUE rb_czmq_loop_remove(VALUE obj, VALUE pollable)
336
+ {
337
+ errno = 0;
338
+ ZmqGetLoop(obj);
339
+ pollable = rb_czmq_pollitem_coerce(pollable);
340
+ ZmqGetPollitem(pollable);
341
+ zloop_poller_end(loop->loop, pollitem->item);
342
+ return Qnil;
343
+ }
344
+
345
+ /*
346
+ * call-seq:
347
+ * loop.register_timer(timer) => true
348
+ *
349
+ * Registers a ZMQ::Timer instance with the reactor.
350
+ *
351
+ * === Examples
352
+ * loop = ZMQ::Loop.new => ZMQ::Loop
353
+ * timer = ZMQ::Timer.new(1, 2){ :fired }
354
+ * loop.register_timer(timer) => true
355
+ *
356
+ */
357
+
358
+ static VALUE rb_czmq_loop_register_timer(VALUE obj, VALUE tm)
359
+ {
360
+ int rc;
361
+ errno = 0;
362
+ ZmqGetLoop(obj);
363
+ ZmqGetTimer(tm);
364
+ rc = zloop_timer(loop->loop, timer->delay, timer->times, rb_czmq_loop_timer_callback, (void *)tm);
365
+ ZmqAssert(rc);
366
+ return Qtrue;
367
+ }
368
+
369
+ /*
370
+ * call-seq:
371
+ * loop.cancel_timer(timer) => nil
372
+ *
373
+ * Cancels a ZMQ::Timer instance previously registered with the reactor.
374
+ *
375
+ * === Examples
376
+ * loop = ZMQ::Loop.new => ZMQ::Loop
377
+ * timer = ZMQ::Timer.new(1, 2){ :fired }
378
+ * loop.register_timer(timer) => true
379
+ * loop.cancel_timer(timer) => nil
380
+ *
381
+ */
382
+
383
+ static VALUE rb_czmq_loop_cancel_timer(VALUE obj, VALUE tm)
384
+ {
385
+ int rc;
386
+ errno = 0;
387
+ ZmqGetLoop(obj);
388
+ ZmqGetTimer(tm);
389
+ rc = zloop_timer_end(loop->loop, (void *)tm);
390
+ ZmqAssert(rc);
391
+ return Qtrue;
392
+ }
393
+
394
+ void _init_rb_czmq_loop()
395
+ {
396
+ intern_call = rb_intern("call");
397
+ intern_readable = rb_intern("on_readable");
398
+ intern_writable = rb_intern("on_writable");
399
+ intern_error = rb_intern("on_error");
400
+
401
+ rb_cZmqLoop = rb_define_class_under(rb_mZmq, "Loop", rb_cObject);
402
+
403
+ rb_define_alloc_func(rb_cZmqLoop, rb_czmq_loop_new);
404
+ rb_define_method(rb_cZmqLoop, "start", rb_czmq_loop_start, 0);
405
+ rb_define_method(rb_cZmqLoop, "stop", rb_czmq_loop_stop, 0);
406
+ rb_define_method(rb_cZmqLoop, "running?", rb_czmq_loop_running_p, 0);
407
+ rb_define_method(rb_cZmqLoop, "destroy", rb_czmq_loop_destroy, 0);
408
+ rb_define_method(rb_cZmqLoop, "verbose=", rb_czmq_loop_set_verbose, 1);
409
+ rb_define_method(rb_cZmqLoop, "register", rb_czmq_loop_register, 1);
410
+ rb_define_method(rb_cZmqLoop, "remove", rb_czmq_loop_remove, 1);
411
+ rb_define_method(rb_cZmqLoop, "register_timer", rb_czmq_loop_register_timer, 1);
412
+ rb_define_method(rb_cZmqLoop, "cancel_timer", rb_czmq_loop_cancel_timer, 1);
413
+ }