rbczmq 0.1

Sign up to get free protection for your applications and to get access to all the features.
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_MESSAGE_H
2
+ #define RBCZMQ_MESSAGE_H
3
+
4
+ #define ZMQ_MESSAGE_DESTROYED 0x01
5
+
6
+ typedef struct {
7
+ zmsg_t *message;
8
+ int flags;
9
+ } zmq_message_wrapper;
10
+
11
+ #define ZmqAssertMessage(obj) ZmqAssertType(obj, rb_cZmqMessage, "ZMQ::Message")
12
+ #define ZmqGetMessage(obj) \
13
+ zmq_message_wrapper *message = NULL; \
14
+ ZmqAssertMessage(obj); \
15
+ Data_Get_Struct(obj, zmq_message_wrapper, message); \
16
+ if (!message) rb_raise(rb_eTypeError, "uninitialized ZMQ message!"); \
17
+ if (message->flags & ZMQ_MESSAGE_DESTROYED) rb_raise(rb_eZmqError, "ZMQ::Message instance %p has been destroyed by the ZMQ framework", (void *)obj);
18
+
19
+ VALUE rb_czmq_alloc_message(zmsg_t *message);
20
+ void rb_czmq_free_message(zmq_message_wrapper *message);
21
+
22
+ void _init_rb_czmq_message();
23
+
24
+ #endif
@@ -0,0 +1,308 @@
1
+ #include <rbczmq_ext.h>
2
+
3
+ /*
4
+ * :nodoc:
5
+ * GC mark callback
6
+ *
7
+ */
8
+ static void rb_czmq_mark_poller(void *ptr)
9
+ {
10
+ zmq_poll_wrapper *poller = (zmq_poll_wrapper *)ptr;
11
+ if (poller) {
12
+ rb_gc_mark(poller->pollables);
13
+ rb_gc_mark(poller->readables);
14
+ rb_gc_mark(poller->writables);
15
+ }
16
+ }
17
+
18
+ /*
19
+ * :nodoc:
20
+ * GC free callback
21
+ *
22
+ */
23
+ static void rb_czmq_free_poller_gc(void *ptr)
24
+ {
25
+ zmq_poll_wrapper *poller = (zmq_poll_wrapper *)ptr;
26
+ if (poller) {
27
+ xfree(poller->pollset);
28
+ xfree(poller);
29
+ }
30
+ }
31
+
32
+ /*
33
+ * :nodoc:
34
+ * Rebuild the pollset from the sockets registered with this poller
35
+ *
36
+ */
37
+ int rb_czmq_poller_rebuild_pollset(zmq_poll_wrapper *poller)
38
+ {
39
+ VALUE pollable;
40
+ int rebuilt;
41
+ xfree(poller->pollset);
42
+ poller->pollset = NULL;
43
+ poller->pollset = ALLOC_N(zmq_pollitem_t, poller->poll_size);
44
+ if (!poller->pollset) return -1;
45
+ for (rebuilt = 0; rebuilt < poller->poll_size; rebuilt++) {
46
+ pollable = rb_ary_entry(poller->pollables, (long)rebuilt);
47
+ ZmqGetPollitem(pollable);
48
+ poller->pollset[rebuilt] = *pollitem->item;
49
+ }
50
+ poller->dirty = FALSE;
51
+ return 0;
52
+ }
53
+
54
+ /*
55
+ * :nodoc:
56
+ * Rebuild the readable and writable arrays if any spoll items are in a ready state
57
+ *
58
+ */
59
+ int rb_czmq_poller_rebuild_selectables(zmq_poll_wrapper *poller)
60
+ {
61
+ VALUE pollable;
62
+ int rebuilt;
63
+ rb_ary_clear(poller->readables);
64
+ rb_ary_clear(poller->writables);
65
+ for (rebuilt = 0; rebuilt < poller->poll_size; rebuilt++) {
66
+ zmq_pollitem_t item = poller->pollset[rebuilt];
67
+ pollable = rb_ary_entry(poller->pollables, (long)rebuilt);
68
+ ZmqGetPollitem(pollable);
69
+ if (item.revents & ZMQ_POLLIN)
70
+ rb_ary_push(poller->readables, rb_czmq_pollitem_pollable(pollable));
71
+ if (item.revents & ZMQ_POLLOUT)
72
+ rb_ary_push(poller->writables, rb_czmq_pollitem_pollable(pollable));
73
+ }
74
+ return 0;
75
+ }
76
+
77
+ /*
78
+ * call-seq:
79
+ * ZMQ::Poller.new => ZMQ::Poller
80
+ *
81
+ * Initializes a new ZMQ::Poller instance.
82
+ *
83
+ * === Examples
84
+ *
85
+ * ZMQ::Poller.new => ZMQ::Poller
86
+ *
87
+ */
88
+ VALUE rb_czmq_poller_new(VALUE obj)
89
+ {
90
+ zmq_poll_wrapper *poller = NULL;
91
+ obj = Data_Make_Struct(rb_cZmqPoller, zmq_poll_wrapper, rb_czmq_mark_poller, rb_czmq_free_poller_gc, poller);
92
+ poller->pollset = NULL;
93
+ poller->pollables = rb_ary_new();
94
+ poller->readables = rb_ary_new();
95
+ poller->writables = rb_ary_new();
96
+ poller->dirty = FALSE;
97
+ poller->verbose = FALSE;
98
+ rb_obj_call_init(obj, 0, NULL);
99
+ return obj;
100
+ }
101
+
102
+ /*
103
+ * :nodoc:
104
+ * Polls a set of sockets / IOs while the GIL is released.
105
+ *
106
+ */
107
+ static VALUE rb_czmq_nogvl_poll(void *ptr)
108
+ {
109
+ struct nogvl_poll_args *args = ptr;
110
+ int rc;
111
+ rc = zmq_poll(args->items, args->nitems, args->timeout);
112
+ return (VALUE)rc;
113
+ }
114
+
115
+ /*
116
+ * call-seq:
117
+ * poller.poll(1) => Fixnum
118
+ *
119
+ * Multiplexes input/output events in a level-triggered fashion over a set of registered sockets.
120
+ *
121
+ * === Examples
122
+ *
123
+ * Supported timeout values :
124
+ *
125
+ * -1 : block until any sockets are ready (no timeout)
126
+ * 0 : non-blocking poll
127
+ * 1 : block for up to 1 second (1000ms)
128
+ * 0.1 : block for up to 0.1 seconds (100ms)
129
+ *
130
+ * poller = ZMQ::Poller.new => ZMQ::Poller
131
+ * poller.register(req) => true
132
+ * poller.poll(1) => Fixnum
133
+ *
134
+ */
135
+ VALUE rb_czmq_poller_poll(int argc, VALUE *argv, VALUE obj)
136
+ {
137
+ VALUE tmout;
138
+ size_t timeout;
139
+ struct nogvl_poll_args args;
140
+ int rc;
141
+ ZmqGetPoller(obj);
142
+ rb_scan_args(argc, argv, "01", &tmout);
143
+ if (NIL_P(tmout)) tmout = INT2NUM(0);
144
+ if (TYPE(tmout) != T_FIXNUM && TYPE(tmout) != T_FLOAT) rb_raise(rb_eTypeError, "wrong timeout type %s (expected Fixnum or Float)", RSTRING_PTR(rb_obj_as_string(tmout)));
145
+ if (poller->poll_size == 0) return INT2NUM(0);
146
+ if (poller->dirty == TRUE) {
147
+ rc = rb_czmq_poller_rebuild_pollset(poller);
148
+ if (rc == -1) rb_raise(rb_eZmqError, "failed in rebuilding the pollset!");
149
+ }
150
+ timeout = (size_t)(((TYPE(tmout) == T_FIXNUM) ? FIX2LONG(tmout) : RFLOAT_VALUE(tmout)) * 1000);
151
+ if (timeout < 0) timeout = -1;
152
+
153
+ args.items = poller->pollset;
154
+ args.nitems = poller->poll_size;
155
+ args.timeout = (long)timeout;
156
+
157
+ rc = (int)rb_thread_blocking_region(rb_czmq_nogvl_poll, (void *)&args, RUBY_UBF_IO, 0);
158
+ ZmqAssert(rc);
159
+ if (rc == 0) {
160
+ rb_ary_clear(poller->readables);
161
+ rb_ary_clear(poller->writables);
162
+ } else {
163
+ rb_czmq_poller_rebuild_selectables(poller);
164
+ }
165
+ return INT2NUM(rc);
166
+ }
167
+
168
+ /*
169
+ * call-seq:
170
+ * poller.register(pollitem) => boolean
171
+ *
172
+ * Registers a poll item for a particular I/O event (ZMQ::POLLIN or ZMQ::POLLOUT) with this poller instance.
173
+ * ZMQ::Socket or Ruby IO instances will automatically be coerced to ZMQ::Pollitem instances with the default
174
+ * events mask (ZMQ::POLLIN | ZMQ::POLLOUT)
175
+ *
176
+ * === Examples
177
+ *
178
+ * Supported events :
179
+ *
180
+ * ZMQ::POLLIN : readable state
181
+ * ZMQ::POLLOUT : writable state
182
+ *
183
+ * poller = ZMQ::Poller.new => ZMQ::Poller
184
+ * poller.register(ZMQ::Pollitem.new(req, ZMQ::POLLIN)) => true
185
+ *
186
+ * poller.register(pub_socket) => true
187
+ * poller.register(STDIN) => true
188
+ *
189
+ */
190
+ VALUE rb_czmq_poller_register(VALUE obj, VALUE pollable)
191
+ {
192
+ ZmqGetPoller(obj);
193
+ pollable = rb_czmq_pollitem_coerce(pollable);
194
+ ZmqGetPollitem(pollable);
195
+ /* Let pollable item be verbose if poller is verbose */
196
+ if (poller->verbose == TRUE) rb_czmq_pollitem_set_verbose(pollable, Qtrue);
197
+ rb_ary_push(poller->pollables, pollable);
198
+ poller->poll_size++;
199
+ poller->dirty = TRUE;
200
+ return pollable;
201
+ }
202
+
203
+ /*
204
+ * call-seq:
205
+ * poller.remove(pollitem) => boolean
206
+ *
207
+ * Removes a poll item from this poller. Deregisters the socket for *any* previously registered events.
208
+ * Note that we match on both poll items as well as pollable entities for all registered poll items.
209
+ *
210
+ * === Examples
211
+ *
212
+ * poller = ZMQ::Poller.new => ZMQ::Poller
213
+ * poller.register(req) => true
214
+ * poller.remove(req) => true
215
+ *
216
+ */
217
+ VALUE rb_czmq_poller_remove(VALUE obj, VALUE pollable)
218
+ {
219
+ int pos;
220
+ VALUE rpollable;
221
+ ZmqGetPoller(obj);
222
+ pollable = rb_czmq_pollitem_coerce(pollable);
223
+ ZmqGetPollitem(pollable);
224
+ for (pos = 0; pos < poller->poll_size; pos++) {
225
+ rpollable = rb_ary_entry(poller->pollables, (long)pos);
226
+ if (pollable == rpollable || rb_czmq_pollitem_pollable(pollable) == rb_czmq_pollitem_pollable(rpollable)) {
227
+ rb_ary_delete(poller->pollables, rpollable);
228
+ poller->poll_size--;
229
+ poller->dirty = TRUE;
230
+ return rpollable;
231
+ }
232
+ }
233
+ return Qfalse;
234
+ }
235
+
236
+ /*
237
+ * call-seq:
238
+ * poller.readables => Array
239
+ *
240
+ * All poll items in a readable state after the last poll.
241
+ *
242
+ * === Examples
243
+ *
244
+ * poller = ZMQ::Poller.new => ZMQ::Poller
245
+ * poller.register(ZMQ::Pollitem(req, ZMQ::POLLIN)) => true
246
+ * poller.poll(1) => 1
247
+ * poller.readables => [req]
248
+ *
249
+ */
250
+ VALUE rb_czmq_poller_readables(VALUE obj)
251
+ {
252
+ ZmqGetPoller(obj);
253
+ return poller->readables;
254
+ }
255
+
256
+ /*
257
+ * call-seq:
258
+ * poller.writables => Array
259
+ *
260
+ * All poll items in a writable state after the last poll.
261
+ *
262
+ * === Examples
263
+ *
264
+ * poller = ZMQ::Poller.new => ZMQ::Poller
265
+ * poller.register(ZMQ::Pollitem(req, ZMQ::POLLOUT)) => true
266
+ * poller.poll(1) => 1
267
+ * poller.writables => [req]
268
+ *
269
+ */
270
+ VALUE rb_czmq_poller_writables(VALUE obj)
271
+ {
272
+ ZmqGetPoller(obj);
273
+ return poller->writables;
274
+ }
275
+
276
+ /*
277
+ * call-seq:
278
+ * poller.verbose = true => nil
279
+ *
280
+ * Logs poller activity to stdout - useful for debugging, but can be quite noisy with lots of activity.
281
+ *
282
+ * === Examples
283
+ * poller = ZMQ::Poller.new => ZMQ::Poller
284
+ * poller.verbose = true => nil
285
+ *
286
+ */
287
+
288
+ static VALUE rb_czmq_poller_set_verbose(VALUE obj, VALUE level)
289
+ {
290
+ Bool vlevel;
291
+ ZmqGetPoller(obj);
292
+ vlevel = (level == Qtrue) ? TRUE : FALSE;
293
+ poller->verbose = vlevel;
294
+ return Qnil;
295
+ }
296
+
297
+ void _init_rb_czmq_poller()
298
+ {
299
+ rb_cZmqPoller = rb_define_class_under(rb_mZmq, "Poller", rb_cObject);
300
+
301
+ rb_define_alloc_func(rb_cZmqPoller, rb_czmq_poller_new);
302
+ rb_define_method(rb_cZmqPoller, "poll", rb_czmq_poller_poll, -1);
303
+ rb_define_method(rb_cZmqPoller, "register", rb_czmq_poller_register, 1);
304
+ rb_define_method(rb_cZmqPoller, "remove", rb_czmq_poller_remove, 1);
305
+ rb_define_method(rb_cZmqPoller, "readables", rb_czmq_poller_readables, 0);
306
+ rb_define_method(rb_cZmqPoller, "writables", rb_czmq_poller_writables, 0);
307
+ rb_define_method(rb_cZmqPoller, "verbose=", rb_czmq_poller_set_verbose, 1);
308
+ }
@@ -0,0 +1,29 @@
1
+ #ifndef RBCZMQ_POLLER_H
2
+ #define RBCZMQ_POLLER_H
3
+
4
+ typedef struct {
5
+ VALUE pollables;
6
+ VALUE readables;
7
+ VALUE writables;
8
+ zmq_pollitem_t *pollset;
9
+ int poll_size;
10
+ Bool dirty;
11
+ Bool verbose;
12
+ } zmq_poll_wrapper;
13
+
14
+ #define ZmqAssertPoller(obj) ZmqAssertType(obj, rb_cZmqPoller, "ZMQ::Poller")
15
+ #define ZmqGetPoller(obj) \
16
+ zmq_poll_wrapper *poller = NULL; \
17
+ ZmqAssertPoller(obj); \
18
+ Data_Get_Struct(obj, zmq_poll_wrapper, poller); \
19
+ if (!poller) rb_raise(rb_eTypeError, "uninitialized ZMQ poller!");
20
+
21
+ struct nogvl_poll_args {
22
+ zmq_pollitem_t *items;
23
+ int nitems;
24
+ long timeout;
25
+ };
26
+
27
+ void _init_rb_czmq_poller();
28
+
29
+ #endif
@@ -0,0 +1,251 @@
1
+ #include <rbczmq_ext.h>
2
+
3
+ /*
4
+ * :nodoc:
5
+ * GC mark callback
6
+ *
7
+ */
8
+ void rb_czmq_mark_pollitem(void *ptr)
9
+ {
10
+ zmq_pollitem_wrapper *pollitem = (zmq_pollitem_wrapper *)ptr;
11
+ if (ptr) {
12
+ rb_gc_mark(pollitem->socket);
13
+ rb_gc_mark(pollitem->io);
14
+ rb_gc_mark(pollitem->events);
15
+ rb_gc_mark(pollitem->handler);
16
+ }
17
+ }
18
+
19
+ /*
20
+ * :nodoc:
21
+ * GC free callback
22
+ *
23
+ */
24
+ void rb_czmq_free_pollitem_gc(void *ptr)
25
+ {
26
+ zmq_pollitem_wrapper *pollitem = (zmq_pollitem_wrapper *)ptr;
27
+ if (ptr) {
28
+ xfree(pollitem->item);
29
+ xfree(pollitem);
30
+ }
31
+ }
32
+
33
+ /*
34
+ * call-seq:
35
+ * ZMQ::Pollitem.new(io, ZMQ:POLLIN) => ZMQ::Pollitem
36
+ *
37
+ * A generic poll item that supports Ruby I/O objects as well as native ZMQ sockets. Poll items are primarily used
38
+ * for registering pollable entities with ZMQ::Poller and ZMQ::Loop instances. If no events given, we default to
39
+ * observing both readable and writable state.
40
+ *
41
+ * === Examples
42
+ *
43
+ * Supported pollable types :
44
+ *
45
+ * IO : any Ruby I/O object (must respond to #fileno as well)
46
+ * ZMQ::Socket : native ZMQ socket
47
+ *
48
+ * Supported events :
49
+ *
50
+ * ZMQ::POLLIN : register for readable events
51
+ * ZMQ::POLLOUT : register for writable events
52
+ *
53
+ * ZMQ::Pollitem.new(io) => ZMQ::Pollitem
54
+ * ZMQ::Pollitem.new(io, ZMQ:POLLIN) => ZMQ::Pollitem
55
+ * ZMQ::Pollitem.new(socket, ZMQ:POLLOUT) => ZMQ::Pollitem
56
+ *
57
+ */
58
+ static VALUE rb_czmq_pollitem_s_new(int argc, VALUE *argv, VALUE obj)
59
+ {
60
+ zmq_sock_wrapper *sock = NULL;
61
+ VALUE pollable, events;
62
+ int evts;
63
+ zmq_pollitem_wrapper *pollitem = NULL;
64
+ rb_scan_args(argc, argv, "11", &pollable, &events);
65
+ if (NIL_P(events)) events = INT2NUM((ZMQ_POLLIN | ZMQ_POLLOUT));
66
+ Check_Type(events, T_FIXNUM);
67
+ evts = NUM2INT(events);
68
+ if (!(evts & ZMQ_POLLIN) && !(evts & ZMQ_POLLOUT))
69
+ rb_raise(rb_eZmqError, "invalid socket event: Only ZMQ::POLLIN and ZMQ::POLLOUT events are supported!");
70
+
71
+ /* XXX: Cleanup allocated struct on any failures below */
72
+ obj = Data_Make_Struct(rb_cZmqPollitem, zmq_pollitem_wrapper, rb_czmq_mark_pollitem, rb_czmq_free_pollitem_gc, pollitem);
73
+ pollitem->events = events;
74
+ pollitem->handler = Qnil;
75
+ pollitem->item = ALLOC(zmq_pollitem_t);
76
+ if (!pollitem->item) rb_memerror();
77
+ pollitem->item->events = evts;
78
+ if (rb_obj_is_kind_of(pollable, rb_cZmqSocket)) {
79
+ GetZmqSocket(pollable);
80
+ ZmqAssertSocketNotPending(sock, "socket in a pending state (not bound or connected) and thus cannot be registered as a poll item!");
81
+ ZmqSockGuardCrossThread(sock);
82
+ pollitem->socket = pollable;
83
+ pollitem->io = Qnil;
84
+ pollitem->item->fd = 0;
85
+ pollitem->item->socket = sock->socket;
86
+ /* Do not block on socket close */
87
+ zsockopt_set_linger(sock->socket, 1);
88
+ } else if (rb_obj_is_kind_of(pollable, rb_cIO)) {
89
+ pollitem->io = pollable;
90
+ pollitem->socket = Qnil;
91
+ pollitem->item->socket = NULL;
92
+ pollitem->item->fd = NUM2INT(rb_funcall(pollable, rb_intern("fileno"), 0));
93
+ /* XXX: handle coercion of other I/O like objects as well ? respond_to?(:fileno) ? */
94
+ } else {
95
+ rb_raise(rb_eTypeError, "wrong pollable type %s (%s). Only objects of type ZMQ::Socket and IO supported.", rb_obj_classname(pollable), RSTRING_PTR(rb_obj_as_string(pollable)));
96
+ }
97
+ rb_obj_call_init(obj, 0, NULL);
98
+ return obj;
99
+ }
100
+
101
+ /*
102
+ * call-seq:
103
+ * ZMQ::Pollitem.coerce(sock) => ZMQ::Pollitem
104
+ *
105
+ * Attempts to coerce a ZMQ::Socket or IO to a ZMQ::Pollitem instance
106
+ *
107
+ * === Examples
108
+ *
109
+ * ZMQ::Pollitem.coerce(sock) => ZMQ::Pollitem
110
+ * ZMQ::Pollitem.coerce(STDOUT) => IO
111
+ *
112
+ */
113
+
114
+ VALUE rb_czmq_pollitem_s_coerce(ZMQ_UNUSED VALUE obj, VALUE pollable)
115
+ {
116
+ VALUE pollitem;
117
+ VALUE args[1];
118
+ if (rb_obj_is_kind_of(pollable, rb_cZmqPollitem)) return pollable;
119
+ args[0] = pollable;
120
+ pollitem = Qnil;
121
+ return rb_czmq_pollitem_s_new(1, args, pollitem);
122
+ }
123
+
124
+ /*
125
+ * :nodoc:
126
+ * Attempt to coerce an object to a ZMQ::Pollitem instance
127
+ *
128
+ */
129
+ VALUE rb_czmq_pollitem_coerce(VALUE pollable)
130
+ {
131
+ return rb_czmq_pollitem_s_coerce(Qnil, pollable);
132
+ }
133
+
134
+ /*
135
+ * call-seq:
136
+ * pollitem.pollable => IO or ZMQ::Socket
137
+ *
138
+ * Returns the pollable entity for this poll item.
139
+ *
140
+ * === Examples
141
+ *
142
+ * item = ZMQ::Pollitem.new(STDOUT) => ZMQ::Pollitem
143
+ * item.pollable => STDOUT
144
+ *
145
+ * item = ZMQ::Pollitem.new(pub_sock) => ZMQ::Pollitem
146
+ * item.pollable => ZMQ::Socket
147
+ *
148
+ */
149
+
150
+ VALUE rb_czmq_pollitem_pollable(VALUE obj)
151
+ {
152
+ ZmqGetPollitem(obj);
153
+ if (NIL_P(pollitem->socket)) return pollitem->io;
154
+ return pollitem->socket;
155
+ }
156
+
157
+ /*
158
+ * call-seq:
159
+ * pollitem.events => Fixnum
160
+ *
161
+ * Returns the I/O events the pollable entity is interested in.
162
+ *
163
+ * === Examples
164
+ *
165
+ * item = ZMQ::Pollitem.new(sock, ZMQ::POLLIN) => ZMQ::Pollitem
166
+ * item.events => ZMQ::POLLIN
167
+ *
168
+ */
169
+
170
+ VALUE rb_czmq_pollitem_events(VALUE obj)
171
+ {
172
+ ZmqGetPollitem(obj);
173
+ return pollitem->events;
174
+ }
175
+
176
+ /*
177
+ * call-seq:
178
+ * pollitem.handler => Object or nil
179
+ *
180
+ * Returns the callback handler currently associated with this poll item.
181
+ *
182
+ * === Examples
183
+ * item = ZMQ::Pollitem.new(sock)
184
+ * item.handler = MyFrameHandler => nil
185
+ * item.handler => MyFrameHandler
186
+ *
187
+ */
188
+
189
+ VALUE rb_czmq_pollitem_handler(VALUE obj)
190
+ {
191
+ ZmqGetPollitem(obj);
192
+ return pollitem->handler;
193
+ }
194
+
195
+ /*
196
+ * call-seq:
197
+ * pollitem.handler = MyFrameHandler => nil
198
+ *
199
+ * Associates a callback handler with this poll item.
200
+ *
201
+ * === Examples
202
+ * item = ZMQ::Pollitem.new(sock)
203
+ * item.handler = MyFrameHandler => nil
204
+ *
205
+ */
206
+
207
+ VALUE rb_czmq_pollitem_handler_equals(VALUE obj, VALUE handler)
208
+ {
209
+ ZmqGetPollitem(obj);
210
+ pollitem->handler = handler;
211
+ return Qnil;
212
+ }
213
+
214
+ /*
215
+ * call-seq:
216
+ * pollitem.verbose = true => nil
217
+ *
218
+ * Logs pollitem activity to stdout - useful for debugging, but can be quite noisy with lots of activity. Only applicable
219
+ * to pollable items of type ZMQ::Socket.
220
+ *
221
+ * === Examples
222
+ * item = ZMQ::Pollitem.new(sock) => ZMQ::Pollitem
223
+ * item.verbose = true => nil
224
+ *
225
+ */
226
+
227
+ VALUE rb_czmq_pollitem_set_verbose(VALUE obj, VALUE level)
228
+ {
229
+ Bool vlevel;
230
+ zmq_sock_wrapper *sock = NULL;
231
+ ZmqGetPollitem(obj);
232
+ vlevel = (level == Qtrue) ? TRUE : FALSE;
233
+ if (rb_obj_is_kind_of(pollitem->socket, rb_cZmqSocket)) {
234
+ GetZmqSocket(pollitem->socket);
235
+ sock->verbose = vlevel;
236
+ }
237
+ return Qnil;
238
+ }
239
+
240
+ void _init_rb_czmq_pollitem()
241
+ {
242
+ rb_cZmqPollitem = rb_define_class_under(rb_mZmq, "Pollitem", rb_cObject);
243
+
244
+ rb_define_singleton_method(rb_cZmqPollitem, "new", rb_czmq_pollitem_s_new, -1);
245
+ rb_define_singleton_method(rb_cZmqPollitem, "coerce", rb_czmq_pollitem_s_coerce, 1);
246
+ rb_define_method(rb_cZmqPollitem, "pollable", rb_czmq_pollitem_pollable, 0);
247
+ rb_define_method(rb_cZmqPollitem, "events", rb_czmq_pollitem_events, 0);
248
+ rb_define_method(rb_cZmqPollitem, "handler", rb_czmq_pollitem_handler, 0);
249
+ rb_define_method(rb_cZmqPollitem, "handler=", rb_czmq_pollitem_handler_equals, 1);
250
+ rb_define_method(rb_cZmqPollitem, "verbose=", rb_czmq_pollitem_set_verbose, 1);
251
+ }