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.
- data/.gitignore +23 -0
- data/.travis.yml +19 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +19 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +247 -0
- data/Rakefile +67 -0
- data/examples/loop.rb +109 -0
- data/examples/poller.rb +37 -0
- data/examples/pub_sub.rb +101 -0
- data/examples/push_pull.rb +104 -0
- data/examples/req_rep.rb +100 -0
- data/ext/czmq.tar.gz +0 -0
- data/ext/rbczmq/context.c +280 -0
- data/ext/rbczmq/context.h +26 -0
- data/ext/rbczmq/extconf.rb +138 -0
- data/ext/rbczmq/frame.c +401 -0
- data/ext/rbczmq/frame.h +24 -0
- data/ext/rbczmq/jruby.h +22 -0
- data/ext/rbczmq/loop.c +413 -0
- data/ext/rbczmq/loop.h +24 -0
- data/ext/rbczmq/message.c +620 -0
- data/ext/rbczmq/message.h +24 -0
- data/ext/rbczmq/poller.c +308 -0
- data/ext/rbczmq/poller.h +29 -0
- data/ext/rbczmq/pollitem.c +251 -0
- data/ext/rbczmq/pollitem.h +25 -0
- data/ext/rbczmq/rbczmq_ext.c +198 -0
- data/ext/rbczmq/rbczmq_ext.h +94 -0
- data/ext/rbczmq/rbczmq_prelude.h +22 -0
- data/ext/rbczmq/rubinius.h +24 -0
- data/ext/rbczmq/ruby18.h +43 -0
- data/ext/rbczmq/ruby19.h +15 -0
- data/ext/rbczmq/socket.c +1570 -0
- data/ext/rbczmq/socket.h +136 -0
- data/ext/rbczmq/timer.c +110 -0
- data/ext/rbczmq/timer.h +23 -0
- data/ext/zeromq.tar.gz +0 -0
- data/lib/rbczmq.rb +3 -0
- data/lib/zmq.rb +77 -0
- data/lib/zmq/context.rb +50 -0
- data/lib/zmq/default_handler.rb +16 -0
- data/lib/zmq/frame.rb +11 -0
- data/lib/zmq/handler.rb +76 -0
- data/lib/zmq/loop.rb +131 -0
- data/lib/zmq/message.rb +9 -0
- data/lib/zmq/poller.rb +22 -0
- data/lib/zmq/pollitem.rb +31 -0
- data/lib/zmq/socket.rb +125 -0
- data/lib/zmq/socket/dealer.rb +33 -0
- data/lib/zmq/socket/pair.rb +39 -0
- data/lib/zmq/socket/pub.rb +30 -0
- data/lib/zmq/socket/pull.rb +29 -0
- data/lib/zmq/socket/push.rb +32 -0
- data/lib/zmq/socket/rep.rb +37 -0
- data/lib/zmq/socket/req.rb +37 -0
- data/lib/zmq/socket/router.rb +38 -0
- data/lib/zmq/socket/sub.rb +27 -0
- data/lib/zmq/timer.rb +12 -0
- data/lib/zmq/version.rb +5 -0
- data/perf/pair.rb +7 -0
- data/perf/pair/local.rb +22 -0
- data/perf/pair/remote.rb +25 -0
- data/perf/pub_sub.rb +7 -0
- data/perf/pub_sub/local.rb +22 -0
- data/perf/pub_sub/remote.rb +25 -0
- data/perf/push_pull.rb +7 -0
- data/perf/push_pull/local.rb +21 -0
- data/perf/push_pull/remote.rb +25 -0
- data/perf/req_rep.rb +7 -0
- data/perf/req_rep/local.rb +35 -0
- data/perf/req_rep/remote.rb +28 -0
- data/perf/runner.rb +142 -0
- data/rbczmq.gemspec +22 -0
- data/test/helper.rb +21 -0
- data/test/socket/test_dealer_socket.rb +14 -0
- data/test/socket/test_pair_socket.rb +24 -0
- data/test/socket/test_pair_sockets.rb +74 -0
- data/test/socket/test_pub_socket.rb +17 -0
- data/test/socket/test_pub_sub_sockets.rb +87 -0
- data/test/socket/test_pull_socket.rb +17 -0
- data/test/socket/test_push_pull_sockets.rb +81 -0
- data/test/socket/test_push_socket.rb +17 -0
- data/test/socket/test_rep_socket.rb +25 -0
- data/test/socket/test_req_rep_sockets.rb +42 -0
- data/test/socket/test_req_socket.rb +27 -0
- data/test/socket/test_router_socket.rb +14 -0
- data/test/socket/test_routing.rb +66 -0
- data/test/socket/test_sub_socket.rb +17 -0
- data/test/test_context.rb +86 -0
- data/test/test_frame.rb +78 -0
- data/test/test_handler.rb +28 -0
- data/test/test_loop.rb +252 -0
- data/test/test_message.rb +201 -0
- data/test/test_poller.rb +154 -0
- data/test/test_pollitem.rb +78 -0
- data/test/test_socket.rb +403 -0
- data/test/test_threading.rb +34 -0
- data/test/test_timer.rb +37 -0
- data/test/test_zmq.rb +62 -0
- 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
|
data/ext/rbczmq/poller.c
ADDED
@@ -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
|
+
}
|
data/ext/rbczmq/poller.h
ADDED
@@ -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
|
+
}
|