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_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
+ }