rbczmq 0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|