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,26 @@
|
|
1
|
+
#ifndef RBCZMQ_CONTEXT_H
|
2
|
+
#define RBCZMQ_CONTEXT_H
|
3
|
+
|
4
|
+
#define ZMQ_CONTEXT_DESTROYED 0x01
|
5
|
+
|
6
|
+
typedef struct {
|
7
|
+
zctx_t *ctx;
|
8
|
+
int flags;
|
9
|
+
} zmq_ctx_wrapper;
|
10
|
+
|
11
|
+
#define ZmqAssertContext(obj) ZmqAssertType(obj, rb_cZmqContext, "ZMQ::Context")
|
12
|
+
#define ZmqGetContext(obj) \
|
13
|
+
zmq_ctx_wrapper *ctx = NULL; \
|
14
|
+
ZmqAssertContext(obj); \
|
15
|
+
Data_Get_Struct(obj, zmq_ctx_wrapper, ctx); \
|
16
|
+
if (!ctx) rb_raise(rb_eTypeError, "uninitialized ZMQ context!"); \
|
17
|
+
if (ctx->flags & ZMQ_CONTEXT_DESTROYED) rb_raise(rb_eZmqError, "ZMQ::Context instance %p has been destroyed by the ZMQ framework", (void *)obj);
|
18
|
+
|
19
|
+
struct nogvl_socket_args {
|
20
|
+
zctx_t *ctx;
|
21
|
+
int type;
|
22
|
+
};
|
23
|
+
|
24
|
+
void _init_rb_czmq_context();
|
25
|
+
|
26
|
+
#endif
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
def sys(cmd, err_msg)
|
7
|
+
p cmd
|
8
|
+
system(cmd) || fail(err_msg)
|
9
|
+
end
|
10
|
+
|
11
|
+
def fail(msg)
|
12
|
+
STDERR.puts msg
|
13
|
+
exit(1)
|
14
|
+
end
|
15
|
+
|
16
|
+
RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
|
17
|
+
|
18
|
+
# XXX fallbacks specific to Darwin for JRuby (does not set these values in RbConfig::CONFIG)
|
19
|
+
LIBEXT = RbConfig::CONFIG['LIBEXT'] || 'a'
|
20
|
+
DLEXT = RbConfig::CONFIG['DLEXT'] || 'bundle'
|
21
|
+
|
22
|
+
cwd = Pathname(File.expand_path(File.dirname(__FILE__)))
|
23
|
+
dst_path = cwd + 'dst'
|
24
|
+
libs_path = dst_path + 'lib'
|
25
|
+
vendor_path = cwd + '..'
|
26
|
+
zmq_path = vendor_path + 'zeromq'
|
27
|
+
czmq_path = vendor_path + 'czmq'
|
28
|
+
zmq_include_path = zmq_path + 'include'
|
29
|
+
czmq_include_path = czmq_path + 'include'
|
30
|
+
|
31
|
+
# Fail early if we don't meet the following dependencies.
|
32
|
+
|
33
|
+
# Present on OS X and BSD systems, package install required on Linux
|
34
|
+
fail("package uuid-dev required (apt-get install uuid-dev)") unless have_header('uuid/uuid.h')
|
35
|
+
|
36
|
+
# Courtesy of EventMachine and @tmm1
|
37
|
+
def check_libs libs = [], fatal = false
|
38
|
+
libs.all? { |lib| have_library(lib) || (abort("could not find library: #{lib}") if fatal) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def check_heads heads = [], fatal = false
|
42
|
+
heads.all? { |head| have_header(head) || (abort("could not find header: #{head}") if fatal)}
|
43
|
+
end
|
44
|
+
|
45
|
+
case RUBY_PLATFORM
|
46
|
+
when /mswin32/, /mingw32/, /bccwin32/
|
47
|
+
check_heads(%w[windows.h winsock.h], true)
|
48
|
+
check_libs(%w[kernel32 rpcrt4 gdi32], true)
|
49
|
+
|
50
|
+
if GNU_CHAIN
|
51
|
+
CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++"
|
52
|
+
else
|
53
|
+
$defs.push "-EHs"
|
54
|
+
$defs.push "-GR"
|
55
|
+
end
|
56
|
+
|
57
|
+
when /solaris/
|
58
|
+
add_define 'OS_SOLARIS8'
|
59
|
+
|
60
|
+
if CONFIG['CC'] == 'cc' and `cc -flags 2>&1` =~ /Sun/ # detect SUNWspro compiler
|
61
|
+
# SUN CHAIN
|
62
|
+
add_define 'CC_SUNWspro'
|
63
|
+
$preload = ["\nCXX = CC"] # hack a CXX= line into the makefile
|
64
|
+
$CFLAGS = CONFIG['CFLAGS'] = "-KPIC"
|
65
|
+
CONFIG['CCDLFLAGS'] = "-KPIC"
|
66
|
+
CONFIG['LDSHARED'] = "$(CXX) -G -KPIC -lCstd"
|
67
|
+
else
|
68
|
+
# GNU CHAIN
|
69
|
+
# on Unix we need a g++ link, not gcc.
|
70
|
+
CONFIG['LDSHARED'] = "$(CXX) -shared"
|
71
|
+
end
|
72
|
+
|
73
|
+
when /openbsd/
|
74
|
+
# OpenBSD branch contributed by Guillaume Sellier.
|
75
|
+
|
76
|
+
# on Unix we need a g++ link, not gcc. On OpenBSD, linking against libstdc++ have to be explicitly done for shared libs
|
77
|
+
CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++ -fPIC"
|
78
|
+
CONFIG['LDSHAREDXX'] = "$(CXX) -shared -lstdc++ -fPIC"
|
79
|
+
|
80
|
+
when /darwin/
|
81
|
+
# on Unix we need a g++ link, not gcc.
|
82
|
+
# Ff line contributed by Daniel Harple.
|
83
|
+
CONFIG['LDSHARED'] = "$(CXX) " + CONFIG['LDSHARED'].split[1..-1].join(' ')
|
84
|
+
|
85
|
+
when /aix/
|
86
|
+
CONFIG['LDSHARED'] = "$(CXX) -shared -Wl,-G -Wl,-brtl"
|
87
|
+
|
88
|
+
else
|
89
|
+
# on Unix we need a g++ link, not gcc.
|
90
|
+
CONFIG['LDSHARED'] = "$(CXX) -shared"
|
91
|
+
end
|
92
|
+
|
93
|
+
# extract dependencies
|
94
|
+
unless File.directory?(zmq_path) && File.directory?(czmq_path)
|
95
|
+
fail "The 'tar' (creates and manipulates streaming archive files) utility is required to extract dependencies" if `which tar`.strip.empty?
|
96
|
+
Dir.chdir(vendor_path) do
|
97
|
+
sys "tar xvzf zeromq.tar.gz", "Could not extract the ZeroMQ archive!"
|
98
|
+
sys "tar xvzf czmq.tar.gz", "Could not extract the CZMQ archive!"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# build libzmq
|
103
|
+
lib = libs_path + "libzmq.#{LIBEXT}"
|
104
|
+
Dir.chdir zmq_path do
|
105
|
+
sys "./autogen.sh", "ZeroMQ autogen failed!" unless File.exist?(zmq_path + 'configure')
|
106
|
+
sys "./configure --prefix=#{dst_path} --without-documentation --enable-shared && make && make install", "ZeroMQ compile error!"
|
107
|
+
end unless File.exist?(lib)
|
108
|
+
|
109
|
+
# build libczmq
|
110
|
+
lib = libs_path + "libczmq.#{LIBEXT}"
|
111
|
+
Dir.chdir czmq_path do
|
112
|
+
sys "./autogen.sh", "CZMQ autogen failed!" unless File.exist?(czmq_path + 'configure')
|
113
|
+
sys "./configure LDFLAGS=-L#{libs_path} --prefix=#{dst_path} --with-libzmq=#{dst_path} --disable-shared && make all && make install", "CZMQ compile error!"
|
114
|
+
end unless File.exist?(lib)
|
115
|
+
|
116
|
+
dir_config('rbczmq')
|
117
|
+
|
118
|
+
have_func('rb_thread_blocking_region')
|
119
|
+
|
120
|
+
$INCFLAGS << " -I#{zmq_include_path}" if find_header("zmq.h", zmq_include_path)
|
121
|
+
$INCFLAGS << " -I#{czmq_include_path}" if find_header("czmq.h", czmq_include_path)
|
122
|
+
|
123
|
+
$LIBPATH << libs_path.to_s
|
124
|
+
|
125
|
+
# Special case to prevent Rubinius compile from linking system libzmq if present
|
126
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/
|
127
|
+
CONFIG['LDSHARED'] = "#{CONFIG['LDSHARED']} -Wl,-rpath=#{libs_path.to_s}"
|
128
|
+
end
|
129
|
+
|
130
|
+
fail "Error compiling and linking libzmq" unless have_library("zmq")
|
131
|
+
fail "Error compiling and linking libczmq" unless have_library("czmq")
|
132
|
+
|
133
|
+
$defs << "-pedantic"
|
134
|
+
|
135
|
+
$CFLAGS << ' -Wall -funroll-loops'
|
136
|
+
$CFLAGS << ' -Wextra -O0 -ggdb3' if ENV['DEBUG']
|
137
|
+
|
138
|
+
create_makefile('rbczmq_ext')
|
data/ext/rbczmq/frame.c
ADDED
@@ -0,0 +1,401 @@
|
|
1
|
+
#include <rbczmq_ext.h>
|
2
|
+
static VALUE intern_data;
|
3
|
+
|
4
|
+
/*
|
5
|
+
* :nodoc:
|
6
|
+
* Callback invoked by zframe_destroy in libczmq. We track all frames coerced to native objects in a symbol table
|
7
|
+
* to guard against a mismatch between allocated frames and the Ruby object space as zframe_destroy is invoked
|
8
|
+
* throughout libczmq (zmsg.c) where the Ruby GC can't easily track it. Ruby MRI Object finalizers are a real
|
9
|
+
* pita to deal with.
|
10
|
+
*
|
11
|
+
*/
|
12
|
+
void rb_czmq_frame_freed(zframe_t *frame)
|
13
|
+
{
|
14
|
+
st_delete(frames_map, (st_data_t*)&frame, 0);
|
15
|
+
}
|
16
|
+
|
17
|
+
/*
|
18
|
+
* :nodoc:
|
19
|
+
* Coerce a zframe instance to a native Ruby object.
|
20
|
+
*
|
21
|
+
*/
|
22
|
+
VALUE rb_czmq_alloc_frame(zframe_t *frame)
|
23
|
+
{
|
24
|
+
VALUE frame_obj;
|
25
|
+
ZmqRegisterFrame(frame);
|
26
|
+
frame_obj = Data_Wrap_Struct(rb_cZmqFrame, 0, rb_czmq_free_frame_gc, frame);
|
27
|
+
rb_obj_call_init(frame_obj, 0, NULL);
|
28
|
+
return frame_obj;
|
29
|
+
}
|
30
|
+
|
31
|
+
/*
|
32
|
+
* :nodoc:
|
33
|
+
* Free all resources for a frame - invoked by the lower level ZMQ::Frame#destroy as well as the GC callback. We also
|
34
|
+
* do a symbol table lookup here to ensure we don't double free a struct that's already been recycled from within
|
35
|
+
* libczmq.
|
36
|
+
*
|
37
|
+
*/
|
38
|
+
void rb_czmq_free_frame(zframe_t *frame)
|
39
|
+
{
|
40
|
+
if (frame)
|
41
|
+
if (st_lookup(frames_map, (st_data_t)frame, 0)) zframe_destroy(&frame);
|
42
|
+
}
|
43
|
+
|
44
|
+
/*
|
45
|
+
* :nodoc:
|
46
|
+
* GC free callback
|
47
|
+
*
|
48
|
+
*/
|
49
|
+
void rb_czmq_free_frame_gc(void *ptr)
|
50
|
+
{
|
51
|
+
zframe_t *frame = (zframe_t *)ptr;
|
52
|
+
rb_czmq_free_frame(frame);
|
53
|
+
}
|
54
|
+
|
55
|
+
/*
|
56
|
+
* call-seq:
|
57
|
+
* ZMQ::Frame.new => ZMQ::Frame
|
58
|
+
* ZMQ::Frame.new("data") => ZMQ::Frame
|
59
|
+
*
|
60
|
+
* Creates a new ZMQ::Frame instance. Can be initialized with or without data. A frame corresponds to one zmq_msg_t.
|
61
|
+
*
|
62
|
+
* === Examples
|
63
|
+
* ZMQ::Frame.new => ZMQ::Frame
|
64
|
+
* ZMQ::Frame.new("data") => ZMQ::Frame
|
65
|
+
*
|
66
|
+
*/
|
67
|
+
|
68
|
+
static VALUE rb_czmq_frame_s_new(int argc, VALUE *argv, VALUE frame)
|
69
|
+
{
|
70
|
+
VALUE data;
|
71
|
+
errno = 0;
|
72
|
+
zframe_t *fr;
|
73
|
+
rb_scan_args(argc, argv, "01", &data);
|
74
|
+
if (NIL_P(data)) {
|
75
|
+
fr = zframe_new(NULL, 0);
|
76
|
+
} else {
|
77
|
+
Check_Type(data, T_STRING);
|
78
|
+
fr = zframe_new(RSTRING_PTR(data), (size_t)RSTRING_LEN(data));
|
79
|
+
}
|
80
|
+
if (fr == NULL) {
|
81
|
+
ZmqAssertSysError();
|
82
|
+
rb_memerror();
|
83
|
+
}
|
84
|
+
ZmqRegisterFrame(fr);
|
85
|
+
frame = Data_Wrap_Struct(rb_cZmqFrame, 0, rb_czmq_free_frame_gc, fr);
|
86
|
+
rb_obj_call_init(frame, 0, NULL);
|
87
|
+
return frame;
|
88
|
+
}
|
89
|
+
|
90
|
+
/*
|
91
|
+
* call-seq:
|
92
|
+
* frame.destroy => nil
|
93
|
+
*
|
94
|
+
* Explicitly destroys an allocated ZMQ::Frame instance. Useful for manual memory management, otherwise the GC
|
95
|
+
* will take the same action if a frame object is not reachable anymore on the next GC cycle. This is
|
96
|
+
* a lower level API.
|
97
|
+
*
|
98
|
+
* === Examples
|
99
|
+
* frame = ZMQ::Frame.new("data") => ZMQ::Frame
|
100
|
+
* frame.destroy => nil
|
101
|
+
*
|
102
|
+
*/
|
103
|
+
|
104
|
+
static VALUE rb_czmq_frame_destroy(VALUE obj)
|
105
|
+
{
|
106
|
+
ZmqGetFrame(obj);
|
107
|
+
rb_czmq_free_frame(frame);
|
108
|
+
return Qnil;
|
109
|
+
}
|
110
|
+
|
111
|
+
/*
|
112
|
+
* call-seq:
|
113
|
+
* frame.size => Fixnum
|
114
|
+
*
|
115
|
+
* Returns the size of the frame.
|
116
|
+
*
|
117
|
+
* === Examples
|
118
|
+
* frame = ZMQ::Frame.new("data") => ZMQ::Frame
|
119
|
+
* frame.size => 4
|
120
|
+
*
|
121
|
+
*/
|
122
|
+
|
123
|
+
static VALUE rb_czmq_frame_size(VALUE obj)
|
124
|
+
{
|
125
|
+
size_t size;
|
126
|
+
ZmqGetFrame(obj);
|
127
|
+
size = zframe_size(frame);
|
128
|
+
return LONG2FIX(size);
|
129
|
+
}
|
130
|
+
|
131
|
+
/*
|
132
|
+
* call-seq:
|
133
|
+
* frame.data => String
|
134
|
+
*
|
135
|
+
* Returns the data represented by the frame as a string.
|
136
|
+
*
|
137
|
+
* === Examples
|
138
|
+
* frame = ZMQ::Frame.new("data") => ZMQ::Frame
|
139
|
+
* frame.data => "data"
|
140
|
+
*
|
141
|
+
*/
|
142
|
+
|
143
|
+
static VALUE rb_czmq_frame_data(VALUE obj)
|
144
|
+
{
|
145
|
+
size_t size;
|
146
|
+
ZmqGetFrame(obj);
|
147
|
+
size = zframe_size(frame);
|
148
|
+
return ZmqEncode(rb_str_new((char *)zframe_data(frame), (long)size));
|
149
|
+
}
|
150
|
+
|
151
|
+
/*
|
152
|
+
* call-seq:
|
153
|
+
* frame.to_s => String
|
154
|
+
*
|
155
|
+
* Returns a String representation of this frame.
|
156
|
+
*
|
157
|
+
* === Examples
|
158
|
+
* frame = ZMQ::Frame.new("data") => ZMQ::Frame
|
159
|
+
* frame.to_s => "data"
|
160
|
+
*
|
161
|
+
*/
|
162
|
+
|
163
|
+
static VALUE rb_czmq_frame_to_s(VALUE obj)
|
164
|
+
{
|
165
|
+
return rb_funcall(obj, intern_data, 0, 0);
|
166
|
+
}
|
167
|
+
|
168
|
+
/*
|
169
|
+
* call-seq:
|
170
|
+
* frame.strhex => String
|
171
|
+
*
|
172
|
+
* Returns a printable hex representation of this frame
|
173
|
+
*
|
174
|
+
* === Examples
|
175
|
+
* frame = ZMQ::Frame.new("message") => ZMQ::Frame
|
176
|
+
* frame.strhex => "6D657373616765"
|
177
|
+
*
|
178
|
+
*/
|
179
|
+
|
180
|
+
static VALUE rb_czmq_frame_strhex(VALUE obj)
|
181
|
+
{
|
182
|
+
ZmqGetFrame(obj);
|
183
|
+
return rb_str_new2(zframe_strhex(frame));
|
184
|
+
}
|
185
|
+
|
186
|
+
/*
|
187
|
+
* call-seq:
|
188
|
+
* frame.dup => ZMQ::Frame
|
189
|
+
*
|
190
|
+
* Returns a copy of the current frame
|
191
|
+
*
|
192
|
+
* === Examples
|
193
|
+
* frame = ZMQ::Frame.new("message") => ZMQ::Frame
|
194
|
+
* frame.dup => ZMQ::Frame
|
195
|
+
*
|
196
|
+
*/
|
197
|
+
|
198
|
+
static VALUE rb_czmq_frame_dup(VALUE obj)
|
199
|
+
{
|
200
|
+
VALUE dup;
|
201
|
+
zframe_t *dup_fr = NULL;
|
202
|
+
errno = 0;
|
203
|
+
ZmqGetFrame(obj);
|
204
|
+
dup_fr = zframe_dup(frame);
|
205
|
+
if (dup_fr == NULL) {
|
206
|
+
ZmqAssertSysError();
|
207
|
+
rb_memerror();
|
208
|
+
}
|
209
|
+
ZmqRegisterFrame(dup_fr);
|
210
|
+
dup = Data_Wrap_Struct(rb_cZmqFrame, 0, rb_czmq_free_frame_gc, dup_fr);
|
211
|
+
rb_obj_call_init(dup, 0, NULL);
|
212
|
+
return dup;
|
213
|
+
}
|
214
|
+
|
215
|
+
/*
|
216
|
+
* call-seq:
|
217
|
+
* frame.data_equals?("data") => boolean
|
218
|
+
*
|
219
|
+
* Determines if the current frame's payload matches a given string
|
220
|
+
*
|
221
|
+
* === Examples
|
222
|
+
* frame = ZMQ::Frame.new("message") => ZMQ::Frame
|
223
|
+
* frame.data_equals?("message") => true
|
224
|
+
*
|
225
|
+
*/
|
226
|
+
|
227
|
+
static VALUE rb_czmq_frame_data_equals_p(VALUE obj, VALUE data)
|
228
|
+
{
|
229
|
+
ZmqGetFrame(obj);
|
230
|
+
Check_Type(data, T_STRING);
|
231
|
+
return (zframe_streq(frame, RSTRING_PTR(data)) == TRUE) ? Qtrue : Qfalse;
|
232
|
+
}
|
233
|
+
|
234
|
+
/*
|
235
|
+
* call-seq:
|
236
|
+
* frame.more? => boolean
|
237
|
+
*
|
238
|
+
* Determines if the current frame is part of a multipart message.
|
239
|
+
*
|
240
|
+
* === Examples
|
241
|
+
* frame = ZMQ::Frame.new("message") => ZMQ::Frame
|
242
|
+
* frame.more? => false
|
243
|
+
*
|
244
|
+
*/
|
245
|
+
|
246
|
+
static VALUE rb_czmq_frame_more_p(VALUE obj)
|
247
|
+
{
|
248
|
+
ZmqGetFrame(obj);
|
249
|
+
return (zframe_more(frame) == ZFRAME_MORE) ? Qtrue : Qfalse;
|
250
|
+
}
|
251
|
+
|
252
|
+
/*
|
253
|
+
* call-seq:
|
254
|
+
* frame.eql?(other) => boolean
|
255
|
+
*
|
256
|
+
* Determines if the current frame is equal to another (identical size and data).
|
257
|
+
*
|
258
|
+
* === Examples
|
259
|
+
* frame = ZMQ::Frame.new("message") => ZMQ::Frame
|
260
|
+
* other_frame = ZMQ::Frame.new("other")
|
261
|
+
* frame.eql?(other_frame) => false
|
262
|
+
*
|
263
|
+
*/
|
264
|
+
|
265
|
+
static VALUE rb_czmq_frame_eql_p(VALUE obj, VALUE other_frame)
|
266
|
+
{
|
267
|
+
zframe_t *other = NULL;
|
268
|
+
ZmqGetFrame(obj);
|
269
|
+
ZmqAssertFrame(other_frame);
|
270
|
+
Data_Get_Struct(other_frame, zframe_t, other);
|
271
|
+
if (!other) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!"); \
|
272
|
+
if (!(st_lookup(frames_map, (st_data_t)other, 0))) rb_raise(rb_eZmqError, "object %p has been destroyed by the ZMQ framework", (void *)other_frame);
|
273
|
+
return (zframe_eq(frame, other)) ? Qtrue : Qfalse;
|
274
|
+
}
|
275
|
+
|
276
|
+
/*
|
277
|
+
* call-seq:
|
278
|
+
* frame == other => boolean
|
279
|
+
*
|
280
|
+
* Determines if the current frame is equal to another (identical size and data).
|
281
|
+
*
|
282
|
+
* === Examples
|
283
|
+
* frame = ZMQ::Frame.new("message") => ZMQ::Frame
|
284
|
+
* other_frame = ZMQ::Frame.new("other")
|
285
|
+
* frame == other_frame => false
|
286
|
+
* frame == frame => true
|
287
|
+
*
|
288
|
+
*/
|
289
|
+
|
290
|
+
static VALUE rb_czmq_frame_equals(VALUE obj, VALUE other_frame)
|
291
|
+
{
|
292
|
+
if (obj == other_frame) return Qtrue;
|
293
|
+
return rb_czmq_frame_eql_p(obj, other_frame);
|
294
|
+
}
|
295
|
+
|
296
|
+
/*
|
297
|
+
* call-seq:
|
298
|
+
* frame <=> other => boolean
|
299
|
+
*
|
300
|
+
* Comparable support for ZMQ::Frame instances.
|
301
|
+
*
|
302
|
+
* === Examples
|
303
|
+
* frame = ZMQ::Frame.new("message") => ZMQ::Frame
|
304
|
+
* other_frame = ZMQ::Frame.new("other")
|
305
|
+
* frame > other_frame => true
|
306
|
+
*
|
307
|
+
*/
|
308
|
+
|
309
|
+
static VALUE rb_czmq_frame_cmp(VALUE obj, VALUE other_frame)
|
310
|
+
{
|
311
|
+
long diff;
|
312
|
+
zframe_t *other = NULL;
|
313
|
+
if (obj == other_frame) return INT2NUM(0);
|
314
|
+
ZmqGetFrame(obj);
|
315
|
+
ZmqAssertFrame(other_frame);
|
316
|
+
Data_Get_Struct(other_frame, zframe_t, other);
|
317
|
+
if (!other) rb_raise(rb_eTypeError, "uninitialized ZMQ frame!"); \
|
318
|
+
if (!(st_lookup(frames_map, (st_data_t)other, 0))) rb_raise(rb_eZmqError, "object %p has been destroyed by the ZMQ framework", (void *)other_frame);
|
319
|
+
diff = (zframe_size(frame) - zframe_size(other));
|
320
|
+
if (diff == 0) return INT2NUM(0);
|
321
|
+
if (diff > 0) return INT2NUM(1);
|
322
|
+
return INT2NUM(-1);
|
323
|
+
}
|
324
|
+
|
325
|
+
/*
|
326
|
+
* call-seq:
|
327
|
+
* frame.print => nil
|
328
|
+
*
|
329
|
+
* Dumps out frame contents to stderr
|
330
|
+
*
|
331
|
+
* === Examples
|
332
|
+
* frame = ZMQ::Frame.new("message") => ZMQ::Frame
|
333
|
+
* frame.print => nil
|
334
|
+
*
|
335
|
+
*/
|
336
|
+
|
337
|
+
static VALUE rb_czmq_frame_print(int argc, VALUE *argv, VALUE obj)
|
338
|
+
{
|
339
|
+
VALUE prefix;
|
340
|
+
const char *print_prefix = NULL;
|
341
|
+
ZmqGetFrame(obj);
|
342
|
+
rb_scan_args(argc, argv, "01", &prefix);
|
343
|
+
if (NIL_P(prefix)) {
|
344
|
+
print_prefix = "";
|
345
|
+
} else {
|
346
|
+
Check_Type(prefix, T_STRING);
|
347
|
+
print_prefix = RSTRING_PTR(prefix);
|
348
|
+
}
|
349
|
+
zframe_print(frame, (char *)print_prefix);
|
350
|
+
return Qnil;
|
351
|
+
}
|
352
|
+
|
353
|
+
/*
|
354
|
+
* call-seq:
|
355
|
+
* frame.reset("new") => nil
|
356
|
+
*
|
357
|
+
* Sets new content for this frame
|
358
|
+
*
|
359
|
+
* === Examples
|
360
|
+
* frame = ZMQ::Frame.new("message") => ZMQ::Frame
|
361
|
+
* frame.reset("new") => nil
|
362
|
+
* frame.data => "new"
|
363
|
+
*
|
364
|
+
*/
|
365
|
+
|
366
|
+
static VALUE rb_czmq_frame_reset(VALUE obj, VALUE data)
|
367
|
+
{
|
368
|
+
errno = 0;
|
369
|
+
ZmqGetFrame(obj);
|
370
|
+
Check_Type(data, T_STRING);
|
371
|
+
zframe_reset(frame, (char *)RSTRING_PTR(data), (size_t)RSTRING_LEN(data));
|
372
|
+
ZmqAssertSysError();
|
373
|
+
return Qnil;
|
374
|
+
}
|
375
|
+
|
376
|
+
void _init_rb_czmq_frame()
|
377
|
+
{
|
378
|
+
intern_data = rb_intern("data");
|
379
|
+
|
380
|
+
rb_cZmqFrame = rb_define_class_under(rb_mZmq, "Frame", rb_cObject);
|
381
|
+
|
382
|
+
rb_define_const(rb_cZmqFrame, "MORE", INT2NUM(ZFRAME_MORE));
|
383
|
+
rb_define_const(rb_cZmqFrame, "REUSE", INT2NUM(ZFRAME_REUSE));
|
384
|
+
|
385
|
+
rb_define_singleton_method(rb_cZmqFrame, "new", rb_czmq_frame_s_new, -1);
|
386
|
+
rb_define_method(rb_cZmqFrame, "destroy", rb_czmq_frame_destroy, 0);
|
387
|
+
rb_define_method(rb_cZmqFrame, "size", rb_czmq_frame_size, 0);
|
388
|
+
rb_define_method(rb_cZmqFrame, "dup", rb_czmq_frame_dup, 0);
|
389
|
+
rb_define_method(rb_cZmqFrame, "data", rb_czmq_frame_data, 0);
|
390
|
+
rb_define_method(rb_cZmqFrame, "to_s", rb_czmq_frame_to_s, 0);
|
391
|
+
rb_define_method(rb_cZmqFrame, "to_str", rb_czmq_frame_to_s, 0);
|
392
|
+
rb_define_method(rb_cZmqFrame, "strhex", rb_czmq_frame_strhex, 0);
|
393
|
+
rb_define_method(rb_cZmqFrame, "data_equals?", rb_czmq_frame_data_equals_p, 1);
|
394
|
+
rb_define_method(rb_cZmqFrame, "more?", rb_czmq_frame_more_p, 0);
|
395
|
+
rb_define_method(rb_cZmqFrame, "eql?", rb_czmq_frame_eql_p, 1);
|
396
|
+
rb_define_method(rb_cZmqFrame, "==", rb_czmq_frame_equals, 1);
|
397
|
+
rb_define_method(rb_cZmqFrame, "<=>", rb_czmq_frame_cmp, 1);
|
398
|
+
rb_define_method(rb_cZmqFrame, "print", rb_czmq_frame_print, -1);
|
399
|
+
rb_define_alias(rb_cZmqFrame, "dump", "print");
|
400
|
+
rb_define_method(rb_cZmqFrame, "reset", rb_czmq_frame_reset, 1);
|
401
|
+
}
|