zeromq 0.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/extension/context.c +156 -0
- data/extension/context.h +24 -0
- data/extension/error.c +14 -0
- data/extension/error.h +7 -0
- data/extension/extconf.rb +41 -0
- data/extension/extension.c +21 -0
- data/extension/extension.h +63 -0
- data/extension/socket.c +591 -0
- data/extension/socket.h +18 -0
- data/extension/zeromq.c +284 -0
- data/extension/zeromq.h +3 -0
- data/lib/zeromq/version.rb +3 -0
- metadata +58 -0
data/extension/context.c
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
//-----------------------------------------------------------------------------
|
2
|
+
|
3
|
+
|
4
|
+
#include "context.h"
|
5
|
+
#include "socket.h"
|
6
|
+
|
7
|
+
//-----------------------------------------------------------------------------
|
8
|
+
|
9
|
+
static VALUE context_allocate( VALUE klass );
|
10
|
+
static void context_free( void* instance );
|
11
|
+
|
12
|
+
static VALUE context_initialize( int argc_, VALUE* argv_, VALUE self );
|
13
|
+
static VALUE context_close( VALUE self );
|
14
|
+
|
15
|
+
//-----------------------------------------------------------------------------
|
16
|
+
|
17
|
+
struct zeromq_context* zeromq_context_create()
|
18
|
+
//--------------------------------------------
|
19
|
+
{
|
20
|
+
struct zeromq_context* context = NULL;
|
21
|
+
|
22
|
+
context = ALLOC( struct zeromq_context );
|
23
|
+
context->context = NULL;
|
24
|
+
context->reference_count = 1;
|
25
|
+
|
26
|
+
return context;
|
27
|
+
}
|
28
|
+
|
29
|
+
void zeromq_context_destroy( struct zeromq_context* context )
|
30
|
+
//-----------------------------------------------------------
|
31
|
+
{
|
32
|
+
assert( context );
|
33
|
+
|
34
|
+
if ( context->context != NULL )
|
35
|
+
{
|
36
|
+
int rc = zmq_ctx_destroy( context->context );
|
37
|
+
assert( rc == 0 );
|
38
|
+
}
|
39
|
+
|
40
|
+
xfree( context );
|
41
|
+
}
|
42
|
+
|
43
|
+
void zeromq_context_retain( struct zeromq_context* context )
|
44
|
+
//----------------------------------------------------------
|
45
|
+
{
|
46
|
+
assert( context );
|
47
|
+
assert( context->context );
|
48
|
+
assert( context->reference_count != 0 );
|
49
|
+
|
50
|
+
context->reference_count++;
|
51
|
+
}
|
52
|
+
|
53
|
+
void zeromq_context_release( struct zeromq_context* context )
|
54
|
+
//-----------------------------------------------------------
|
55
|
+
{
|
56
|
+
assert( context );
|
57
|
+
assert( context->context );
|
58
|
+
assert( context->reference_count != 0 );
|
59
|
+
|
60
|
+
context->reference_count--;
|
61
|
+
|
62
|
+
if ( context->reference_count == 0 )
|
63
|
+
{
|
64
|
+
zeromq_context_destroy( context );
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
//-----------------------------------------------------------------------------
|
69
|
+
|
70
|
+
VALUE context_declare( VALUE zeromq_module )
|
71
|
+
//------------------------------------------
|
72
|
+
{
|
73
|
+
VALUE klass = rb_define_class_under(
|
74
|
+
zeromq_module,
|
75
|
+
"Context",
|
76
|
+
rb_cObject
|
77
|
+
);
|
78
|
+
|
79
|
+
rb_define_singleton_method(
|
80
|
+
klass,
|
81
|
+
"default",
|
82
|
+
context_default,
|
83
|
+
0
|
84
|
+
);
|
85
|
+
|
86
|
+
rb_define_alloc_func( klass, context_allocate );
|
87
|
+
rb_define_method( klass, "initialize", context_initialize, -1 );
|
88
|
+
rb_define_method( klass, "close", context_close, 0 );
|
89
|
+
|
90
|
+
return klass;
|
91
|
+
}
|
92
|
+
|
93
|
+
VALUE context_default( VALUE self )
|
94
|
+
//---------------------------------
|
95
|
+
{
|
96
|
+
static VALUE default_context = Qnil;
|
97
|
+
|
98
|
+
if ( default_context == Qnil )
|
99
|
+
{
|
100
|
+
default_context = rb_class_new_instance( 0, NULL, self );
|
101
|
+
}
|
102
|
+
|
103
|
+
return default_context;
|
104
|
+
}
|
105
|
+
|
106
|
+
static VALUE context_allocate( VALUE class )
|
107
|
+
//------------------------------------------
|
108
|
+
{
|
109
|
+
return rb_data_object_alloc(
|
110
|
+
class,
|
111
|
+
zeromq_context_create(),
|
112
|
+
0,
|
113
|
+
context_free
|
114
|
+
);
|
115
|
+
}
|
116
|
+
|
117
|
+
static void context_free( void* instance )
|
118
|
+
//----------------------------------------
|
119
|
+
{
|
120
|
+
zeromq_context_destroy( ( struct zeromq_context* )instance );
|
121
|
+
}
|
122
|
+
|
123
|
+
static VALUE context_initialize( int arg_count, VALUE* args, VALUE self )
|
124
|
+
//------------------------------------------------------------------------
|
125
|
+
{
|
126
|
+
VALUE context_options = Qnil;
|
127
|
+
rb_scan_args( arg_count, args, "01", &context_options );
|
128
|
+
|
129
|
+
struct zeromq_context* context = NULL;
|
130
|
+
Data_Get_Struct( self, void, context );
|
131
|
+
|
132
|
+
assert( context->context == NULL );
|
133
|
+
|
134
|
+
context->context = zmq_ctx_new();
|
135
|
+
if ( !context->context )
|
136
|
+
{
|
137
|
+
rb_raise( exception_type, "%s", zmq_strerror( zmq_errno() ) );
|
138
|
+
return Qnil;
|
139
|
+
}
|
140
|
+
|
141
|
+
return self;
|
142
|
+
}
|
143
|
+
|
144
|
+
static VALUE context_close( VALUE self )
|
145
|
+
//--------------------------------------
|
146
|
+
{
|
147
|
+
struct zeromq_context* context = NULL;
|
148
|
+
Data_Get_Struct( self, void, context );
|
149
|
+
|
150
|
+
if ( context->context != NULL )
|
151
|
+
{
|
152
|
+
zeromq_context_destroy( context );
|
153
|
+
}
|
154
|
+
|
155
|
+
return Qnil;
|
156
|
+
}
|
data/extension/context.h
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#include "extension.h"
|
2
|
+
|
3
|
+
//-----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
struct zeromq_context
|
6
|
+
{
|
7
|
+
void* context;
|
8
|
+
unsigned reference_count;
|
9
|
+
};
|
10
|
+
|
11
|
+
//-----------------------------------------------------------------------------
|
12
|
+
|
13
|
+
struct zeromq_context* zeromq_context_default();
|
14
|
+
|
15
|
+
struct zeromq_context* zeromq_context_create();
|
16
|
+
void zeromq_context_destroy( struct zeromq_context* context );
|
17
|
+
|
18
|
+
void zeromq_context_retain( struct zeromq_context* context );
|
19
|
+
void zeromq_context_release( struct zeromq_context* context );
|
20
|
+
|
21
|
+
//-----------------------------------------------------------------------------
|
22
|
+
|
23
|
+
VALUE context_declare( VALUE zeromq_module );
|
24
|
+
VALUE context_default( VALUE self );
|
data/extension/error.c
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
//-----------------------------------------------------------------------------
|
2
|
+
|
3
|
+
#include "error.h"
|
4
|
+
|
5
|
+
//-----------------------------------------------------------------------------
|
6
|
+
|
7
|
+
VALUE error_declare( VALUE zeromq_module )
|
8
|
+
{
|
9
|
+
return rb_define_class_under(
|
10
|
+
zeromq_module,
|
11
|
+
"Error",
|
12
|
+
rb_eRuntimeError
|
13
|
+
);
|
14
|
+
}
|
data/extension/error.h
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
dir_config( 'zeromq' )
|
3
|
+
|
4
|
+
def header?
|
5
|
+
|
6
|
+
have_header( 'zmq.h' ) ||
|
7
|
+
find_header(
|
8
|
+
'zmq.h',
|
9
|
+
'/opt/local/include',
|
10
|
+
'/usr/local/include',
|
11
|
+
'/usr/include'
|
12
|
+
)
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def library?
|
17
|
+
|
18
|
+
have_library( 'zmq', 'zmq_init' ) ||
|
19
|
+
find_library(
|
20
|
+
'zmq',
|
21
|
+
'zmq_init',
|
22
|
+
'/opt/local/lib',
|
23
|
+
'/usr/local/lib',
|
24
|
+
'/usr/lib'
|
25
|
+
)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
if header? && library?
|
30
|
+
|
31
|
+
puts "Cool, I found your zmq install..."
|
32
|
+
|
33
|
+
create_makefile( 'zeromq' )
|
34
|
+
|
35
|
+
else
|
36
|
+
|
37
|
+
raise "Couldn't find zmq library. try setting --with-zmq-dir=<path> to tell me where it is."
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#include "extension.h"
|
2
|
+
|
3
|
+
#include "zeromq.h"
|
4
|
+
#include "error.h"
|
5
|
+
#include "context.h"
|
6
|
+
#include "socket.h"
|
7
|
+
|
8
|
+
VALUE module;
|
9
|
+
VALUE exception_type;
|
10
|
+
VALUE context_class;
|
11
|
+
VALUE socket_class;
|
12
|
+
|
13
|
+
void Init_zeromq()
|
14
|
+
//----------------
|
15
|
+
{
|
16
|
+
module = module_declare();
|
17
|
+
|
18
|
+
exception_type = error_declare( module );
|
19
|
+
context_class = context_declare( module );
|
20
|
+
socket_class = socket_declare( module );
|
21
|
+
}
|
@@ -0,0 +1,63 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (c) 2007-2010 iMatix Corporation
|
3
|
+
|
4
|
+
This file is part of 0MQ.
|
5
|
+
|
6
|
+
0MQ is free software; you can redistribute it and/or modify it under
|
7
|
+
the terms of the Lesser GNU General Public License as published by
|
8
|
+
the Free Software Foundation; either version 3 of the License, or
|
9
|
+
(at your option) any later version.
|
10
|
+
|
11
|
+
0MQ is distributed in the hope that it will be useful,
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
Lesser GNU General Public License for more details.
|
15
|
+
|
16
|
+
You should have received a copy of the Lesser GNU General Public License
|
17
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
*/
|
19
|
+
|
20
|
+
#include <assert.h>
|
21
|
+
#include <string.h>
|
22
|
+
#include <ruby.h>
|
23
|
+
#ifdef HAVE_RUBY_IO_H
|
24
|
+
#include <ruby/io.h>
|
25
|
+
#else
|
26
|
+
#include <rubyio.h>
|
27
|
+
#endif
|
28
|
+
#include <zmq.h>
|
29
|
+
|
30
|
+
#if defined _MSC_VER
|
31
|
+
#ifndef int8_t
|
32
|
+
typedef __int8 int8_t;
|
33
|
+
#endif
|
34
|
+
#ifndef int16_t
|
35
|
+
typedef __int16 int16_t;
|
36
|
+
#endif
|
37
|
+
#ifndef int32_t
|
38
|
+
typedef __int32 int32_t;
|
39
|
+
#endif
|
40
|
+
#ifndef int64_t
|
41
|
+
typedef __int64 int64_t;
|
42
|
+
#endif
|
43
|
+
#ifndef uint8_t
|
44
|
+
typedef unsigned __int8 uint8_t;
|
45
|
+
#endif
|
46
|
+
#ifndef uint16_t
|
47
|
+
typedef unsigned __int16 uint16_t;
|
48
|
+
#endif
|
49
|
+
#ifndef uint32_t
|
50
|
+
typedef unsigned __int32 uint32_t;
|
51
|
+
#endif
|
52
|
+
#ifndef uint64_t
|
53
|
+
typedef unsigned __int64 uint64_t;
|
54
|
+
#endif
|
55
|
+
#else
|
56
|
+
#include <stdint.h>
|
57
|
+
#endif
|
58
|
+
|
59
|
+
//-----------------------------------------------------------------------------
|
60
|
+
|
61
|
+
extern VALUE context_class;
|
62
|
+
extern VALUE socket_class;
|
63
|
+
extern VALUE exception_type;
|
data/extension/socket.c
ADDED
@@ -0,0 +1,591 @@
|
|
1
|
+
//-----------------------------------------------------------------------------
|
2
|
+
|
3
|
+
#include "socket.h"
|
4
|
+
#include "context.h"
|
5
|
+
|
6
|
+
//-----------------------------------------------------------------------------
|
7
|
+
|
8
|
+
#define Check_Socket(__socket) \
|
9
|
+
do {\
|
10
|
+
if ((__socket->socket) == NULL)\
|
11
|
+
rb_raise (rb_eIOError, "closed socket");\
|
12
|
+
} while(0)
|
13
|
+
|
14
|
+
//-----------------------------------------------------------------------------
|
15
|
+
// ZeroMQ::Socket method declarations
|
16
|
+
|
17
|
+
static VALUE socket_allocate( VALUE socket_class );
|
18
|
+
void socket_free( void* instance );
|
19
|
+
|
20
|
+
static VALUE socket_initialize( int count, VALUE* arguments, VALUE self );
|
21
|
+
static VALUE socket_close( VALUE self );
|
22
|
+
|
23
|
+
static VALUE socket_getsockopt( VALUE self, VALUE option );
|
24
|
+
static VALUE socket_setsockopt( VALUE self, VALUE option, VALUE value );
|
25
|
+
static VALUE socket_bind( VALUE self, VALUE addr_ );
|
26
|
+
static VALUE socket_connect( VALUE self, VALUE addr_ );
|
27
|
+
|
28
|
+
static VALUE socket_recv( int argc_, VALUE* argv_, VALUE self_ );
|
29
|
+
static VALUE socket_send( int argc_, VALUE* argv_, VALUE self_ );
|
30
|
+
|
31
|
+
//-----------------------------------------------------------------------------
|
32
|
+
// zeromq socket helper functions
|
33
|
+
|
34
|
+
struct zeromq_socket* zeromq_socket_create()
|
35
|
+
//------------------------------------------
|
36
|
+
{
|
37
|
+
struct zeromq_socket* socket;
|
38
|
+
|
39
|
+
socket = ALLOC( struct zeromq_socket );
|
40
|
+
socket->context = NULL;
|
41
|
+
socket->socket = NULL;
|
42
|
+
|
43
|
+
return socket;
|
44
|
+
}
|
45
|
+
|
46
|
+
void zeromq_socket_destroy( struct zeromq_socket* zeromq_socket )
|
47
|
+
//---------------------------------------------------------------
|
48
|
+
{
|
49
|
+
if ( zeromq_socket->socket != NULL )
|
50
|
+
{
|
51
|
+
int rc = zmq_close( zeromq_socket->socket );
|
52
|
+
assert( rc == 0 );
|
53
|
+
}
|
54
|
+
|
55
|
+
if ( zeromq_socket->context != NULL )
|
56
|
+
{
|
57
|
+
zeromq_context_release( zeromq_socket->context );
|
58
|
+
}
|
59
|
+
|
60
|
+
xfree( zeromq_socket );
|
61
|
+
}
|
62
|
+
|
63
|
+
int zeromq_apply_socket_option( VALUE option, VALUE value, VALUE socket )
|
64
|
+
//-----------------------------------------------------------------------
|
65
|
+
{
|
66
|
+
socket_setsockopt( socket, option, value );
|
67
|
+
return ST_CONTINUE;
|
68
|
+
}
|
69
|
+
|
70
|
+
//-----------------------------------------------------------------------------
|
71
|
+
// ZeroMQ::Socket class initialization
|
72
|
+
|
73
|
+
VALUE socket_declare( VALUE zeromq_module )
|
74
|
+
//-----------------------------------------
|
75
|
+
{
|
76
|
+
VALUE klass = Qnil;
|
77
|
+
|
78
|
+
klass = rb_define_class_under( zeromq_module, "Socket", rb_cObject );
|
79
|
+
rb_define_alloc_func( klass, socket_allocate );
|
80
|
+
|
81
|
+
rb_define_method( klass, "initialize", socket_initialize, -1 );
|
82
|
+
rb_define_method( klass, "getsockopt", socket_getsockopt, 1 );
|
83
|
+
rb_define_method( klass, "setsockopt", socket_setsockopt, 2 );
|
84
|
+
rb_define_method( klass, "bind", socket_bind, 1 );
|
85
|
+
rb_define_method( klass, "connect", socket_connect, 1 );
|
86
|
+
rb_define_method( klass, "send", socket_send, -1 );
|
87
|
+
rb_define_method( klass, "recv", socket_recv, -1 );
|
88
|
+
rb_define_method( klass, "close", socket_close, 0 );
|
89
|
+
|
90
|
+
return klass;
|
91
|
+
}
|
92
|
+
|
93
|
+
//-----------------------------------------------------------------------------
|
94
|
+
// ZeroMQ::Socket method implmentation
|
95
|
+
|
96
|
+
static VALUE socket_allocate( VALUE socket_class )
|
97
|
+
//------------------------------------------------
|
98
|
+
{
|
99
|
+
return rb_data_object_alloc(
|
100
|
+
socket_class,
|
101
|
+
zeromq_socket_create(),
|
102
|
+
0,
|
103
|
+
socket_free
|
104
|
+
);
|
105
|
+
}
|
106
|
+
|
107
|
+
void socket_free( void* instance )
|
108
|
+
//--------------------------------
|
109
|
+
{
|
110
|
+
zeromq_socket_destroy( ( struct zeromq_socket* )instance );
|
111
|
+
}
|
112
|
+
|
113
|
+
static VALUE socket_initialize( int arg_count, VALUE* arguments, VALUE self )
|
114
|
+
//---------------------------------------------------------------------------
|
115
|
+
{
|
116
|
+
struct zeromq_socket* socket = NULL;
|
117
|
+
Data_Get_Struct( self, void, socket );
|
118
|
+
|
119
|
+
VALUE context = Qnil;
|
120
|
+
VALUE socket_type = Qnil;
|
121
|
+
VALUE socket_options = Qnil;
|
122
|
+
|
123
|
+
rb_scan_args(
|
124
|
+
arg_count,
|
125
|
+
arguments,
|
126
|
+
"12",
|
127
|
+
&context,
|
128
|
+
&socket_type,
|
129
|
+
&socket_options
|
130
|
+
);
|
131
|
+
|
132
|
+
if ( CLASS_OF( context ) != context_class )
|
133
|
+
{
|
134
|
+
socket_options = socket_type;
|
135
|
+
socket_type = context;
|
136
|
+
context = Qnil;
|
137
|
+
}
|
138
|
+
|
139
|
+
if ( context == Qnil )
|
140
|
+
{
|
141
|
+
context = context_default( context_class );
|
142
|
+
}
|
143
|
+
|
144
|
+
if ( socket_type == Qnil )
|
145
|
+
{
|
146
|
+
rb_raise( exception_type, "The socket type is required." );
|
147
|
+
return Qnil;
|
148
|
+
}
|
149
|
+
|
150
|
+
struct zeromq_context* context_struct = NULL;
|
151
|
+
Data_Get_Struct( context, void, context_struct );
|
152
|
+
|
153
|
+
socket->socket = zmq_socket(
|
154
|
+
context_struct->context,
|
155
|
+
NUM2INT( socket_type )
|
156
|
+
);
|
157
|
+
|
158
|
+
if ( !socket->socket )
|
159
|
+
{
|
160
|
+
rb_raise( exception_type, "%s", zmq_strerror( zmq_errno() ) );
|
161
|
+
return Qnil;
|
162
|
+
}
|
163
|
+
|
164
|
+
socket->context = context_struct;
|
165
|
+
zeromq_context_retain( socket->context );
|
166
|
+
|
167
|
+
if ( CLASS_OF( socket_options ) == rb_cHash )
|
168
|
+
{
|
169
|
+
rb_hash_foreach( socket_options, zeromq_apply_socket_option, self );
|
170
|
+
}
|
171
|
+
|
172
|
+
return self;
|
173
|
+
}
|
174
|
+
|
175
|
+
static VALUE socket_close( VALUE self_ )
|
176
|
+
//--------------------------------------
|
177
|
+
{
|
178
|
+
struct zeromq_socket * s;
|
179
|
+
Data_Get_Struct (self_, struct zeromq_socket, s);
|
180
|
+
if (s->socket != NULL) {
|
181
|
+
int rc = zmq_close(s->socket);
|
182
|
+
if (rc != 0) {
|
183
|
+
rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
|
184
|
+
return Qnil;
|
185
|
+
}
|
186
|
+
|
187
|
+
s->socket = NULL;
|
188
|
+
|
189
|
+
/* Decrement the refcounter for the context (and possibly free it). */
|
190
|
+
zeromq_context_release( s->context );
|
191
|
+
s->context = NULL;
|
192
|
+
}
|
193
|
+
return Qnil;
|
194
|
+
}
|
195
|
+
|
196
|
+
static VALUE socket_getsockopt( VALUE self_, VALUE option_ )
|
197
|
+
{
|
198
|
+
int rc = 0;
|
199
|
+
VALUE retval;
|
200
|
+
struct zeromq_socket * s;
|
201
|
+
|
202
|
+
Data_Get_Struct (self_, struct zeromq_socket, s);
|
203
|
+
Check_Socket (s);
|
204
|
+
|
205
|
+
switch ( NUM2INT( option_ ) )
|
206
|
+
{
|
207
|
+
case ZMQ_FD:
|
208
|
+
{
|
209
|
+
#ifdef _WIN32
|
210
|
+
SOCKET optval;
|
211
|
+
#else
|
212
|
+
int optval;
|
213
|
+
#endif
|
214
|
+
size_t optvalsize = sizeof( optval );
|
215
|
+
|
216
|
+
rc = zmq_getsockopt(
|
217
|
+
s->socket,
|
218
|
+
NUM2INT( option_ ),
|
219
|
+
( void* )&optval,
|
220
|
+
&optvalsize
|
221
|
+
);
|
222
|
+
|
223
|
+
if ( rc != 0 )
|
224
|
+
{
|
225
|
+
rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
|
226
|
+
return Qnil;
|
227
|
+
}
|
228
|
+
|
229
|
+
if ( NUM2INT( option_ ) == ZMQ_RCVMORE )
|
230
|
+
retval = optval ? Qtrue : Qfalse;
|
231
|
+
else
|
232
|
+
retval = INT2NUM (optval);
|
233
|
+
}
|
234
|
+
break;
|
235
|
+
|
236
|
+
case ZMQ_EVENTS:
|
237
|
+
{
|
238
|
+
uint32_t optval;
|
239
|
+
size_t optvalsize = sizeof(optval);
|
240
|
+
|
241
|
+
rc = zmq_getsockopt(
|
242
|
+
s->socket,
|
243
|
+
NUM2INT( option_ ),
|
244
|
+
( void* )&optval,
|
245
|
+
&optvalsize
|
246
|
+
);
|
247
|
+
|
248
|
+
if ( rc != 0 )
|
249
|
+
{
|
250
|
+
rb_raise( exception_type, "%s", zmq_strerror( zmq_errno() ) );
|
251
|
+
return Qnil;
|
252
|
+
}
|
253
|
+
|
254
|
+
if ( NUM2INT( option_ ) == ZMQ_RCVMORE )
|
255
|
+
retval = optval ? Qtrue : Qfalse;
|
256
|
+
else
|
257
|
+
retval = INT2NUM( optval );
|
258
|
+
}
|
259
|
+
break;
|
260
|
+
|
261
|
+
case ZMQ_TYPE:
|
262
|
+
case ZMQ_LINGER:
|
263
|
+
case ZMQ_RECONNECT_IVL:
|
264
|
+
case ZMQ_BACKLOG:
|
265
|
+
case ZMQ_RECONNECT_IVL_MAX:
|
266
|
+
case ZMQ_SNDTIMEO:
|
267
|
+
case ZMQ_RCVTIMEO:
|
268
|
+
case ZMQ_RCVHWM:
|
269
|
+
case ZMQ_SNDHWM:
|
270
|
+
{
|
271
|
+
int optval;
|
272
|
+
size_t optvalsize = sizeof( optval );
|
273
|
+
|
274
|
+
rc = zmq_getsockopt(
|
275
|
+
s->socket,
|
276
|
+
NUM2INT( option_ ),
|
277
|
+
( void* )&optval,
|
278
|
+
&optvalsize
|
279
|
+
);
|
280
|
+
|
281
|
+
if ( rc != 0 )
|
282
|
+
{
|
283
|
+
rb_raise( exception_type, "%s", zmq_strerror( zmq_errno() ) );
|
284
|
+
return Qnil;
|
285
|
+
}
|
286
|
+
|
287
|
+
if ( NUM2INT( option_ ) == ZMQ_RCVMORE )
|
288
|
+
retval = optval ? Qtrue : Qfalse;
|
289
|
+
else
|
290
|
+
retval = INT2NUM (optval);
|
291
|
+
}
|
292
|
+
break;
|
293
|
+
|
294
|
+
case ZMQ_RCVMORE:
|
295
|
+
case ZMQ_AFFINITY:
|
296
|
+
case ZMQ_RATE:
|
297
|
+
case ZMQ_RECOVERY_IVL:
|
298
|
+
case ZMQ_SNDBUF:
|
299
|
+
case ZMQ_RCVBUF:
|
300
|
+
{
|
301
|
+
int64_t optval;
|
302
|
+
size_t optvalsize = sizeof(optval);
|
303
|
+
|
304
|
+
rc = zmq_getsockopt (s->socket, NUM2INT (option_), (void *)&optval,
|
305
|
+
&optvalsize);
|
306
|
+
|
307
|
+
if (rc != 0) {
|
308
|
+
rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
|
309
|
+
return Qnil;
|
310
|
+
}
|
311
|
+
|
312
|
+
if (NUM2INT (option_) == ZMQ_RCVMORE)
|
313
|
+
retval = optval ? Qtrue : Qfalse;
|
314
|
+
else
|
315
|
+
retval = INT2NUM (optval);
|
316
|
+
}
|
317
|
+
break;
|
318
|
+
|
319
|
+
case ZMQ_IDENTITY:
|
320
|
+
{
|
321
|
+
char identity[255];
|
322
|
+
size_t optvalsize = sizeof (identity);
|
323
|
+
|
324
|
+
rc = zmq_getsockopt (s->socket, NUM2INT (option_),
|
325
|
+
(void *)identity, &optvalsize);
|
326
|
+
|
327
|
+
if (rc != 0) {
|
328
|
+
rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
|
329
|
+
return Qnil;
|
330
|
+
}
|
331
|
+
|
332
|
+
if (optvalsize > sizeof (identity))
|
333
|
+
optvalsize = sizeof (identity);
|
334
|
+
|
335
|
+
retval = rb_str_new (identity, optvalsize);
|
336
|
+
}
|
337
|
+
break;
|
338
|
+
|
339
|
+
default:
|
340
|
+
rb_raise (exception_type, "%s", zmq_strerror (EINVAL));
|
341
|
+
return Qnil;
|
342
|
+
}
|
343
|
+
|
344
|
+
return retval;
|
345
|
+
}
|
346
|
+
|
347
|
+
static VALUE socket_setsockopt (VALUE self_, VALUE option_, VALUE optval_)
|
348
|
+
{
|
349
|
+
int rc = 0;
|
350
|
+
struct zeromq_socket * s;
|
351
|
+
|
352
|
+
Data_Get_Struct (self_, struct zeromq_socket, s);
|
353
|
+
Check_Socket (s);
|
354
|
+
|
355
|
+
switch ( NUM2INT( option_ ) )
|
356
|
+
{
|
357
|
+
case ZMQ_AFFINITY:
|
358
|
+
case ZMQ_RATE:
|
359
|
+
case ZMQ_RECOVERY_IVL:
|
360
|
+
case ZMQ_SNDBUF:
|
361
|
+
case ZMQ_RCVBUF:
|
362
|
+
{
|
363
|
+
uint64_t optval = FIX2LONG (optval_);
|
364
|
+
|
365
|
+
// Forward the code to native 0MQ library.
|
366
|
+
rc = zmq_setsockopt(
|
367
|
+
s->socket,
|
368
|
+
NUM2INT( option_ ),
|
369
|
+
( void* ) &optval,
|
370
|
+
sizeof( optval )
|
371
|
+
);
|
372
|
+
}
|
373
|
+
break;
|
374
|
+
|
375
|
+
case ZMQ_RCVHWM:
|
376
|
+
case ZMQ_SNDHWM:
|
377
|
+
case ZMQ_LINGER:
|
378
|
+
case ZMQ_RECONNECT_IVL:
|
379
|
+
case ZMQ_BACKLOG:
|
380
|
+
case ZMQ_RECONNECT_IVL_MAX:
|
381
|
+
case ZMQ_SNDTIMEO:
|
382
|
+
case ZMQ_RCVTIMEO:
|
383
|
+
{
|
384
|
+
int optval = FIX2INT (optval_);
|
385
|
+
|
386
|
+
// Forward the code to native 0MQ library.
|
387
|
+
rc = zmq_setsockopt(
|
388
|
+
s->socket,
|
389
|
+
NUM2INT( option_ ),
|
390
|
+
( void* )&optval,
|
391
|
+
sizeof( optval )
|
392
|
+
);
|
393
|
+
}
|
394
|
+
break;
|
395
|
+
|
396
|
+
case ZMQ_IDENTITY:
|
397
|
+
case ZMQ_SUBSCRIBE:
|
398
|
+
case ZMQ_UNSUBSCRIBE:
|
399
|
+
{
|
400
|
+
// Forward the code to native 0MQ library.
|
401
|
+
rc = zmq_setsockopt(
|
402
|
+
s->socket,
|
403
|
+
NUM2INT( option_ ),
|
404
|
+
( void* )StringValueCStr( optval_ ),
|
405
|
+
RSTRING_LEN( optval_ )
|
406
|
+
);
|
407
|
+
}
|
408
|
+
break;
|
409
|
+
|
410
|
+
default:
|
411
|
+
{
|
412
|
+
rb_raise( exception_type, "%s", zmq_strerror( EINVAL ) );
|
413
|
+
return Qnil;
|
414
|
+
}
|
415
|
+
}
|
416
|
+
|
417
|
+
if ( rc != 0 )
|
418
|
+
{
|
419
|
+
rb_raise( exception_type, "%s", zmq_strerror( zmq_errno() ) );
|
420
|
+
return Qnil;
|
421
|
+
}
|
422
|
+
|
423
|
+
return self_;
|
424
|
+
}
|
425
|
+
|
426
|
+
static VALUE socket_bind( VALUE self_, VALUE addr_ )
|
427
|
+
{
|
428
|
+
struct zeromq_socket * s;
|
429
|
+
Data_Get_Struct (self_, struct zeromq_socket, s);
|
430
|
+
Check_Socket (s);
|
431
|
+
|
432
|
+
int rc = zmq_bind (s->socket, rb_string_value_cstr (&addr_));
|
433
|
+
if (rc != 0) {
|
434
|
+
rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
|
435
|
+
return Qnil;
|
436
|
+
}
|
437
|
+
|
438
|
+
return Qnil;
|
439
|
+
}
|
440
|
+
|
441
|
+
static VALUE socket_connect( VALUE self_, VALUE addr_ )
|
442
|
+
{
|
443
|
+
struct zeromq_socket * s;
|
444
|
+
Data_Get_Struct (self_, struct zeromq_socket, s);
|
445
|
+
Check_Socket (s);
|
446
|
+
|
447
|
+
int rc = zmq_connect (s->socket, rb_string_value_cstr (&addr_));
|
448
|
+
if (rc != 0) {
|
449
|
+
rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
|
450
|
+
return Qnil;
|
451
|
+
}
|
452
|
+
|
453
|
+
return Qnil;
|
454
|
+
}
|
455
|
+
|
456
|
+
#ifdef HAVE_RUBY_INTERN_H
|
457
|
+
struct zmq_send_recv_args {
|
458
|
+
void *socket;
|
459
|
+
zmq_msg_t *msg;
|
460
|
+
int flags;
|
461
|
+
int rc;
|
462
|
+
};
|
463
|
+
|
464
|
+
static VALUE zmq_send_blocking( void* args_ )
|
465
|
+
{
|
466
|
+
struct zmq_send_recv_args *send_args = (struct zmq_send_recv_args *)args_;
|
467
|
+
|
468
|
+
send_args->rc = zmq_sendmsg(
|
469
|
+
send_args->socket,
|
470
|
+
send_args->msg,
|
471
|
+
send_args->flags
|
472
|
+
);
|
473
|
+
|
474
|
+
return Qnil;
|
475
|
+
}
|
476
|
+
#endif
|
477
|
+
|
478
|
+
static VALUE socket_send (int argc_, VALUE* argv_, VALUE self_)
|
479
|
+
{
|
480
|
+
VALUE msg_, flags_;
|
481
|
+
|
482
|
+
rb_scan_args (argc_, argv_, "11", &msg_, &flags_);
|
483
|
+
|
484
|
+
struct zeromq_socket * s;
|
485
|
+
Data_Get_Struct (self_, struct zeromq_socket, s);
|
486
|
+
Check_Socket (s);
|
487
|
+
|
488
|
+
Check_Type (msg_, T_STRING);
|
489
|
+
|
490
|
+
int flags = NIL_P (flags_) ? 0 : NUM2INT (flags_);
|
491
|
+
|
492
|
+
zmq_msg_t msg;
|
493
|
+
int msg_len = (int)RSTRING_LEN (msg_);
|
494
|
+
int rc = zmq_msg_init_size (&msg, msg_len);
|
495
|
+
if (rc != 0) {
|
496
|
+
rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
|
497
|
+
return Qnil;
|
498
|
+
}
|
499
|
+
memcpy (zmq_msg_data (&msg), RSTRING_PTR (msg_), msg_len);
|
500
|
+
|
501
|
+
#ifdef HAVE_RUBY_INTERN_H
|
502
|
+
if (!(flags & ZMQ_NOBLOCK)) {
|
503
|
+
struct zmq_send_recv_args send_args;
|
504
|
+
send_args.socket = s->socket;
|
505
|
+
send_args.msg = &msg;
|
506
|
+
send_args.flags = flags;
|
507
|
+
rb_thread_blocking_region (zmq_send_blocking, (void*) &send_args, NULL, NULL);
|
508
|
+
rc = send_args.rc;
|
509
|
+
}
|
510
|
+
else
|
511
|
+
#endif
|
512
|
+
rc = zmq_sendmsg( s->socket, &msg, flags );
|
513
|
+
if (rc != 0 && zmq_errno () == EAGAIN) {
|
514
|
+
rc = zmq_msg_close (&msg);
|
515
|
+
assert (rc == 0);
|
516
|
+
return Qfalse;
|
517
|
+
}
|
518
|
+
|
519
|
+
if (rc != 0) {
|
520
|
+
rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
|
521
|
+
rc = zmq_msg_close (&msg);
|
522
|
+
assert (rc == 0);
|
523
|
+
return Qnil;
|
524
|
+
}
|
525
|
+
|
526
|
+
rc = zmq_msg_close (&msg);
|
527
|
+
assert (rc == 0);
|
528
|
+
return Qtrue;
|
529
|
+
}
|
530
|
+
|
531
|
+
#ifdef HAVE_RUBY_INTERN_H
|
532
|
+
static VALUE zmq_recv_blocking (void* args_)
|
533
|
+
{
|
534
|
+
struct zmq_send_recv_args *recv_args = (struct zmq_send_recv_args *)args_;
|
535
|
+
|
536
|
+
recv_args->rc = zmq_recvmsg(recv_args->socket, recv_args->msg, recv_args->flags);
|
537
|
+
|
538
|
+
return Qnil;
|
539
|
+
}
|
540
|
+
#endif
|
541
|
+
|
542
|
+
static VALUE socket_recv (int argc_, VALUE* argv_, VALUE self_)
|
543
|
+
{
|
544
|
+
VALUE flags_;
|
545
|
+
|
546
|
+
rb_scan_args (argc_, argv_, "01", &flags_);
|
547
|
+
|
548
|
+
struct zeromq_socket * s;
|
549
|
+
Data_Get_Struct (self_, struct zeromq_socket, s);
|
550
|
+
Check_Socket (s);
|
551
|
+
|
552
|
+
int flags = NIL_P (flags_) ? 0 : NUM2INT (flags_);
|
553
|
+
|
554
|
+
zmq_msg_t msg;
|
555
|
+
int rc = zmq_msg_init (&msg);
|
556
|
+
assert (rc == 0);
|
557
|
+
|
558
|
+
#ifdef HAVE_RUBY_INTERN_H
|
559
|
+
if (!(flags & ZMQ_NOBLOCK)) {
|
560
|
+
struct zmq_send_recv_args recv_args;
|
561
|
+
recv_args.socket = s->socket;
|
562
|
+
recv_args.msg = &msg;
|
563
|
+
recv_args.flags = flags;
|
564
|
+
rb_thread_blocking_region (zmq_recv_blocking, (void*) &recv_args,
|
565
|
+
NULL, NULL);
|
566
|
+
rc = recv_args.rc;
|
567
|
+
}
|
568
|
+
else
|
569
|
+
#endif
|
570
|
+
rc = zmq_recvmsg(s->socket, &msg, flags);
|
571
|
+
if (rc == -1 && zmq_errno () == EAGAIN) {
|
572
|
+
rc = zmq_msg_close (&msg);
|
573
|
+
assert (rc == 0);
|
574
|
+
return Qnil;
|
575
|
+
}
|
576
|
+
|
577
|
+
if (rc == -1) {
|
578
|
+
rb_raise (exception_type, "%s", zmq_strerror (zmq_errno ()));
|
579
|
+
rc = zmq_msg_close (&msg);
|
580
|
+
assert (rc == 0);
|
581
|
+
return Qnil;
|
582
|
+
}
|
583
|
+
|
584
|
+
VALUE message = rb_str_new ((char*) zmq_msg_data (&msg),
|
585
|
+
zmq_msg_size (&msg));
|
586
|
+
rc = zmq_msg_close (&msg);
|
587
|
+
assert (rc == 0);
|
588
|
+
return message;
|
589
|
+
}
|
590
|
+
|
591
|
+
|
data/extension/socket.h
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#include "extension.h"
|
2
|
+
|
3
|
+
//-----------------------------------------------------------------------------
|
4
|
+
|
5
|
+
struct zeromq_socket
|
6
|
+
{
|
7
|
+
void* socket;
|
8
|
+
struct zeromq_context* context;
|
9
|
+
};
|
10
|
+
|
11
|
+
//-----------------------------------------------------------------------------
|
12
|
+
|
13
|
+
struct zeromq_socket* zeromq_socket_create();
|
14
|
+
void zeromq_socket_destroy( struct zeromq_socket* );
|
15
|
+
|
16
|
+
//-----------------------------------------------------------------------------
|
17
|
+
|
18
|
+
VALUE socket_declare( VALUE zeromq_module );
|
data/extension/zeromq.c
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
//-----------------------------------------------------------------------------
|
2
|
+
|
3
|
+
#include "zeromq.h"
|
4
|
+
#include "socket.h"
|
5
|
+
|
6
|
+
//-----------------------------------------------------------------------------
|
7
|
+
|
8
|
+
static VALUE module_version( VALUE self );
|
9
|
+
static VALUE module_select( int argument_count, VALUE* arguments, VALUE self );
|
10
|
+
|
11
|
+
//-----------------------------------------------------------------------------
|
12
|
+
|
13
|
+
VALUE module_declare()
|
14
|
+
//--------------------
|
15
|
+
{
|
16
|
+
VALUE zmq_module = rb_define_module( "ZeroMQ" );
|
17
|
+
|
18
|
+
rb_define_singleton_method( zmq_module, "version", module_version, 0 );
|
19
|
+
rb_define_singleton_method( zmq_module, "select", module_select, -1 );
|
20
|
+
|
21
|
+
rb_define_const (zmq_module, "SNDHWM", INT2NUM (ZMQ_SNDHWM));
|
22
|
+
rb_define_const (zmq_module, "RCVHWM", INT2NUM (ZMQ_RCVHWM));
|
23
|
+
rb_define_const (zmq_module, "AFFINITY", INT2NUM (ZMQ_AFFINITY));
|
24
|
+
rb_define_const (zmq_module, "IDENTITY", INT2NUM (ZMQ_IDENTITY));
|
25
|
+
rb_define_const (zmq_module, "SUBSCRIBE", INT2NUM (ZMQ_SUBSCRIBE));
|
26
|
+
rb_define_const (zmq_module, "UNSUBSCRIBE", INT2NUM (ZMQ_UNSUBSCRIBE));
|
27
|
+
rb_define_const (zmq_module, "RATE", INT2NUM (ZMQ_RATE));
|
28
|
+
rb_define_const (zmq_module, "RECOVERY_IVL", INT2NUM (ZMQ_RECOVERY_IVL));
|
29
|
+
rb_define_const (zmq_module, "SNDBUF", INT2NUM (ZMQ_SNDBUF));
|
30
|
+
rb_define_const (zmq_module, "RCVBUF", INT2NUM (ZMQ_RCVBUF));
|
31
|
+
rb_define_const (zmq_module, "SNDMORE", INT2NUM (ZMQ_SNDMORE));
|
32
|
+
rb_define_const (zmq_module, "RCVMORE", INT2NUM (ZMQ_RCVMORE));
|
33
|
+
rb_define_const (zmq_module, "FD", INT2NUM (ZMQ_FD));
|
34
|
+
rb_define_const (zmq_module, "EVENTS", INT2NUM (ZMQ_EVENTS));
|
35
|
+
rb_define_const (zmq_module, "TYPE", INT2NUM (ZMQ_TYPE));
|
36
|
+
rb_define_const (zmq_module, "LINGER", INT2NUM (ZMQ_LINGER));
|
37
|
+
rb_define_const (zmq_module, "RECONNECT_IVL", INT2NUM (ZMQ_RECONNECT_IVL));
|
38
|
+
rb_define_const (zmq_module, "BACKLOG", INT2NUM (ZMQ_BACKLOG));
|
39
|
+
rb_define_const (zmq_module, "RECONNECT_IVL_MAX", INT2NUM (ZMQ_RECONNECT_IVL_MAX));
|
40
|
+
rb_define_const (zmq_module, "RECOVERY_IVL_MSEC", INT2NUM (ZMQ_RECOVERY_IVL));
|
41
|
+
rb_define_const (zmq_module, "SNDTIMEO", INT2NUM (ZMQ_SNDTIMEO));
|
42
|
+
rb_define_const (zmq_module, "RCVTIMEO", INT2NUM (ZMQ_RCVTIMEO));
|
43
|
+
rb_define_const (zmq_module, "NOBLOCK", INT2NUM (ZMQ_NOBLOCK));
|
44
|
+
rb_define_const (zmq_module, "PAIR", INT2NUM (ZMQ_PAIR));
|
45
|
+
rb_define_const (zmq_module, "SUB", INT2NUM (ZMQ_SUB));
|
46
|
+
rb_define_const (zmq_module, "PUB", INT2NUM (ZMQ_PUB));
|
47
|
+
rb_define_const (zmq_module, "REQ", INT2NUM (ZMQ_REQ));
|
48
|
+
rb_define_const (zmq_module, "REP", INT2NUM (ZMQ_REP));
|
49
|
+
|
50
|
+
return zmq_module;
|
51
|
+
}
|
52
|
+
|
53
|
+
static VALUE module_version( VALUE self_ )
|
54
|
+
{
|
55
|
+
int major, minor, patch;
|
56
|
+
|
57
|
+
zmq_version(&major, &minor, &patch);
|
58
|
+
|
59
|
+
return rb_ary_new3 (3, INT2NUM (major), INT2NUM (minor), INT2NUM (patch));
|
60
|
+
}
|
61
|
+
|
62
|
+
struct poll_state {
|
63
|
+
int event;
|
64
|
+
int nitems;
|
65
|
+
zmq_pollitem_t *items;
|
66
|
+
VALUE io_objects;
|
67
|
+
};
|
68
|
+
|
69
|
+
typedef VALUE(*iterfunc)(ANYARGS);
|
70
|
+
|
71
|
+
static VALUE poll_add_item(VALUE io_, void *ps_) {
|
72
|
+
struct poll_state *state = (struct poll_state *)ps_;
|
73
|
+
|
74
|
+
long i;
|
75
|
+
|
76
|
+
for (i = 0; i < RARRAY_LEN (state->io_objects); i++) {
|
77
|
+
if (RARRAY_PTR (state->io_objects)[i] == io_) {
|
78
|
+
#ifdef HAVE_RUBY_IO_H
|
79
|
+
state->items[i].events |= state->event;
|
80
|
+
return Qnil;
|
81
|
+
#else
|
82
|
+
if (CLASS_OF (io_) == socket_class) {
|
83
|
+
state->items[i].events |= state->event;
|
84
|
+
return Qnil;
|
85
|
+
}
|
86
|
+
|
87
|
+
OpenFile *fptr;
|
88
|
+
GetOpenFile (io_, fptr);
|
89
|
+
|
90
|
+
if (state->event == ZMQ_POLLOUT &&
|
91
|
+
GetWriteFile (fptr) != NULL &&
|
92
|
+
fileno (GetWriteFile (fptr)) != state->items[i].fd) {
|
93
|
+
break;
|
94
|
+
}
|
95
|
+
else {
|
96
|
+
state->items[i].events |= state->event;
|
97
|
+
return Qnil;
|
98
|
+
}
|
99
|
+
#endif
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
/* Not found in array. Add a new poll item. */
|
104
|
+
rb_ary_push (state->io_objects, io_);
|
105
|
+
|
106
|
+
zmq_pollitem_t *item = &state->items[state->nitems];
|
107
|
+
state->nitems++;
|
108
|
+
|
109
|
+
item->events = state->event;
|
110
|
+
|
111
|
+
if (CLASS_OF (io_) == socket_class) {
|
112
|
+
struct zeromq_socket* socket;
|
113
|
+
Data_Get_Struct( io_, struct zeromq_socket, socket );
|
114
|
+
|
115
|
+
item->socket = socket->socket;
|
116
|
+
item->fd = -1;
|
117
|
+
}
|
118
|
+
else {
|
119
|
+
item->socket = NULL;
|
120
|
+
|
121
|
+
#ifdef HAVE_RUBY_IO_H
|
122
|
+
rb_io_t *fptr;
|
123
|
+
|
124
|
+
GetOpenFile (io_, fptr);
|
125
|
+
item->fd = fileno (rb_io_stdio_file (fptr));
|
126
|
+
#else
|
127
|
+
OpenFile *fptr;
|
128
|
+
|
129
|
+
GetOpenFile (io_, fptr);
|
130
|
+
|
131
|
+
if (state->event == ZMQ_POLLIN && GetReadFile (fptr) != NULL) {
|
132
|
+
item->fd = fileno (GetReadFile (fptr));
|
133
|
+
}
|
134
|
+
else if (state->event == ZMQ_POLLOUT && GetWriteFile (fptr) != NULL) {
|
135
|
+
item->fd = fileno (GetWriteFile (fptr));
|
136
|
+
}
|
137
|
+
else if (state->event == ZMQ_POLLERR) {
|
138
|
+
if (GetReadFile(fptr) != NULL)
|
139
|
+
item->fd = fileno (GetReadFile (fptr));
|
140
|
+
else
|
141
|
+
item->fd = fileno (GetWriteFile (fptr));
|
142
|
+
}
|
143
|
+
#endif
|
144
|
+
}
|
145
|
+
|
146
|
+
return Qnil;
|
147
|
+
}
|
148
|
+
|
149
|
+
#ifdef HAVE_RUBY_INTERN_H
|
150
|
+
|
151
|
+
struct zmq_poll_args {
|
152
|
+
zmq_pollitem_t *items;
|
153
|
+
int nitems;
|
154
|
+
long timeout_usec;
|
155
|
+
int rc;
|
156
|
+
};
|
157
|
+
|
158
|
+
static VALUE zmq_poll_blocking (void* args_)
|
159
|
+
{
|
160
|
+
struct zmq_poll_args *poll_args = (struct zmq_poll_args *)args_;
|
161
|
+
|
162
|
+
poll_args->rc = zmq_poll (poll_args->items, poll_args->nitems, poll_args->timeout_usec);
|
163
|
+
|
164
|
+
return Qnil;
|
165
|
+
}
|
166
|
+
|
167
|
+
#endif
|
168
|
+
|
169
|
+
struct select_arg {
|
170
|
+
VALUE readset;
|
171
|
+
VALUE writeset;
|
172
|
+
VALUE errset;
|
173
|
+
long timeout_usec;
|
174
|
+
zmq_pollitem_t *items;
|
175
|
+
};
|
176
|
+
|
177
|
+
static VALUE internal_select(VALUE argval)
|
178
|
+
{
|
179
|
+
struct select_arg *arg = (struct select_arg *)argval;
|
180
|
+
|
181
|
+
int rc, nitems, i;
|
182
|
+
zmq_pollitem_t *item;
|
183
|
+
|
184
|
+
struct poll_state ps;
|
185
|
+
ps.nitems = 0;
|
186
|
+
ps.items = arg->items;
|
187
|
+
ps.io_objects = rb_ary_new ();
|
188
|
+
|
189
|
+
if (!NIL_P (arg->readset)) {
|
190
|
+
ps.event = ZMQ_POLLIN;
|
191
|
+
rb_iterate(rb_each, arg->readset, (iterfunc)poll_add_item, (VALUE)&ps);
|
192
|
+
}
|
193
|
+
|
194
|
+
if (!NIL_P (arg->writeset)) {
|
195
|
+
ps.event = ZMQ_POLLOUT;
|
196
|
+
rb_iterate(rb_each, arg->writeset, (iterfunc)poll_add_item, (VALUE)&ps);
|
197
|
+
}
|
198
|
+
|
199
|
+
if (!NIL_P (arg->errset)) {
|
200
|
+
ps.event = ZMQ_POLLERR;
|
201
|
+
rb_iterate(rb_each, arg->errset, (iterfunc)poll_add_item, (VALUE)&ps);
|
202
|
+
}
|
203
|
+
|
204
|
+
/* Reset nitems to the actual number of zmq_pollitem_t records we're sending. */
|
205
|
+
nitems = ps.nitems;
|
206
|
+
|
207
|
+
#ifdef HAVE_RUBY_INTERN_H
|
208
|
+
if (arg->timeout_usec != 0) {
|
209
|
+
struct zmq_poll_args poll_args;
|
210
|
+
poll_args.items = ps.items;
|
211
|
+
poll_args.nitems = ps.nitems;
|
212
|
+
poll_args.timeout_usec = arg->timeout_usec;
|
213
|
+
|
214
|
+
rb_thread_blocking_region (zmq_poll_blocking, (void*)&poll_args, NULL, NULL);
|
215
|
+
rc = poll_args.rc;
|
216
|
+
}
|
217
|
+
else
|
218
|
+
#endif
|
219
|
+
rc = zmq_poll (ps.items, ps.nitems, arg->timeout_usec);
|
220
|
+
|
221
|
+
if (rc == -1) {
|
222
|
+
rb_raise(exception_type, "%s", zmq_strerror (zmq_errno ()));
|
223
|
+
return Qnil;
|
224
|
+
}
|
225
|
+
else if (rc == 0)
|
226
|
+
return Qnil;
|
227
|
+
|
228
|
+
VALUE read_active = rb_ary_new ();
|
229
|
+
VALUE write_active = rb_ary_new ();
|
230
|
+
VALUE err_active = rb_ary_new ();
|
231
|
+
|
232
|
+
for (i = 0, item = &ps.items[0]; i < nitems; i++, item++) {
|
233
|
+
if (item->revents != 0) {
|
234
|
+
VALUE io = RARRAY_PTR (ps.io_objects)[i];
|
235
|
+
|
236
|
+
if (item->revents & ZMQ_POLLIN)
|
237
|
+
rb_ary_push (read_active, io);
|
238
|
+
if (item->revents & ZMQ_POLLOUT)
|
239
|
+
rb_ary_push (write_active, io);
|
240
|
+
if (item->revents & ZMQ_POLLERR)
|
241
|
+
rb_ary_push (err_active, io);
|
242
|
+
}
|
243
|
+
}
|
244
|
+
|
245
|
+
return rb_ary_new3 (3, read_active, write_active, err_active);
|
246
|
+
}
|
247
|
+
|
248
|
+
static VALUE module_select_internal(VALUE readset, VALUE writeset, VALUE errset, long timeout_usec)
|
249
|
+
{
|
250
|
+
size_t nitems;
|
251
|
+
struct select_arg arg;
|
252
|
+
|
253
|
+
/* Conservative estimate for nitems before we traverse the lists. */
|
254
|
+
nitems = (NIL_P (readset) ? 0 : RARRAY_LEN (readset)) +
|
255
|
+
(NIL_P (writeset) ? 0 : RARRAY_LEN (writeset)) +
|
256
|
+
(NIL_P (errset) ? 0 : RARRAY_LEN (errset));
|
257
|
+
arg.items = ALLOC_N(zmq_pollitem_t, nitems);
|
258
|
+
|
259
|
+
arg.readset = readset;
|
260
|
+
arg.writeset = writeset;
|
261
|
+
arg.errset = errset;
|
262
|
+
arg.timeout_usec = timeout_usec;
|
263
|
+
|
264
|
+
return rb_ensure(internal_select, (VALUE)&arg, (VALUE (*)())xfree, (VALUE)arg.items);
|
265
|
+
}
|
266
|
+
|
267
|
+
static VALUE module_select (int argc_, VALUE* argv_, VALUE self_)
|
268
|
+
{
|
269
|
+
VALUE readset, writeset, errset, timeout;
|
270
|
+
rb_scan_args (argc_, argv_, "13", &readset, &writeset, &errset, &timeout);
|
271
|
+
|
272
|
+
long timeout_usec;
|
273
|
+
|
274
|
+
if (!NIL_P (readset)) Check_Type (readset, T_ARRAY);
|
275
|
+
if (!NIL_P (writeset)) Check_Type (writeset, T_ARRAY);
|
276
|
+
if (!NIL_P (errset)) Check_Type (errset, T_ARRAY);
|
277
|
+
|
278
|
+
if (NIL_P (timeout))
|
279
|
+
timeout_usec = -1;
|
280
|
+
else
|
281
|
+
timeout_usec = (long)(NUM2DBL (timeout) * 1000000);
|
282
|
+
|
283
|
+
return module_select_internal(readset, writeset, errset, timeout_usec);
|
284
|
+
}
|
data/extension/zeromq.h
ADDED
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zeromq
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kristoph Cichocki-Romanov
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-24 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: This gem provides a Ruby API for the ZeroMQ messaging library.
|
15
|
+
email:
|
16
|
+
- open-source@kristoph.net
|
17
|
+
executables: []
|
18
|
+
extensions:
|
19
|
+
- extension/extconf.rb
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- extension/context.c
|
23
|
+
- extension/error.c
|
24
|
+
- extension/extension.c
|
25
|
+
- extension/socket.c
|
26
|
+
- extension/zeromq.c
|
27
|
+
- extension/context.h
|
28
|
+
- extension/error.h
|
29
|
+
- extension/extension.h
|
30
|
+
- extension/socket.h
|
31
|
+
- extension/zeromq.h
|
32
|
+
- lib/zeromq/version.rb
|
33
|
+
- extension/extconf.rb
|
34
|
+
homepage:
|
35
|
+
licenses: []
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.8.24
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: Ruby API for ZeroMQ
|
58
|
+
test_files: []
|