ffi-rxs 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+
2
+ module XS
3
+
4
+ class XSError < StandardError
5
+ attr_reader :source, :result_code, :error_code, :message
6
+
7
+ def initialize source, result_code, error_code, message
8
+ @source = source
9
+ @result_code = result_code
10
+ @error_code = error_code
11
+ @message = "msg [#{message}], error code [#{error_code}], rc [#{result_code}]"
12
+ super message
13
+ end
14
+ end # call XSError
15
+
16
+
17
+ class ContextError < XSError
18
+ # True when the exception was raised due to the library
19
+ # returning EINVAL.
20
+ #
21
+ # Occurs when he number of app_threads requested is less
22
+ # than one, or the number of io_threads requested is
23
+ # negative.
24
+ #
25
+ def einval?() EINVAL == @error_code; end
26
+
27
+ # True when the exception was raised due to the library
28
+ # returning ETERM.
29
+ #
30
+ # The associated context was terminated.
31
+ #
32
+ def eterm?() ETERM == @error_code; end
33
+
34
+ end # class ContextError
35
+
36
+
37
+ class MessageError < XSError
38
+ # True when the exception was raised due to the library
39
+ # returning ENOMEM.
40
+ #
41
+ # Only ever raised by the #Message class when it fails
42
+ # to allocate sufficient memory to send a message.
43
+ #
44
+ def enomem?() ENOMEM == @error_code; end
45
+ end
46
+
47
+ end # module XS
@@ -0,0 +1,47 @@
1
+
2
+ module ZMQ
3
+
4
+ class ZeroMQError < StandardError
5
+ attr_reader :source, :result_code, :error_code, :message
6
+
7
+ def initialize source, result_code, error_code, message
8
+ @source = source
9
+ @result_code = result_code
10
+ @error_code = error_code
11
+ @message = "msg [#{message}], error code [#{error_code}], rc [#{result_code}]"
12
+ super message
13
+ end
14
+ end # call ZeroMQError
15
+
16
+
17
+ class ContextError < ZeroMQError
18
+ # True when the exception was raised due to the library
19
+ # returning EINVAL.
20
+ #
21
+ # Occurs when he number of app_threads requested is less
22
+ # than one, or the number of io_threads requested is
23
+ # negative.
24
+ #
25
+ def einval?() EINVAL == @error_code; end
26
+
27
+ # True when the exception was raised due to the library
28
+ # returning ETERM.
29
+ #
30
+ # The associated context was terminated.
31
+ #
32
+ def eterm?() ETERM == @error_code; end
33
+
34
+ end # class ContextError
35
+
36
+
37
+ class MessageError < ZeroMQError
38
+ # True when the exception was raised due to the library
39
+ # returning ENOMEM.
40
+ #
41
+ # Only ever raised by the #Message class when it fails
42
+ # to allocate sufficient memory to send a message.
43
+ #
44
+ def enomem?() ENOMEM == @error_code; end
45
+ end
46
+
47
+ end # module ZMQ
@@ -0,0 +1,19 @@
1
+
2
+ module LibC
3
+ extend FFI::Library
4
+ # figures out the correct libc for each platform including Windows
5
+ library = ffi_lib(FFI::Library::LIBC).first
6
+
7
+ # Size_t not working properly on Windows
8
+ find_type(:size_t) rescue typedef(:ulong, :size_t)
9
+
10
+ # memory allocators
11
+ attach_function :malloc, [:size_t], :pointer
12
+ attach_function :free, [:pointer], :void
13
+
14
+ # get a pointer to the free function; used for XS::Message deallocation
15
+ Free = library.find_symbol('free')
16
+
17
+ # memory movers
18
+ attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
19
+ end # module LibC
@@ -0,0 +1,19 @@
1
+
2
+ module LibC
3
+ extend FFI::Library
4
+ # figures out the correct libc for each platform including Windows
5
+ library = ffi_lib(FFI::Library::LIBC).first
6
+
7
+ # Size_t not working properly on Windows
8
+ find_type(:size_t) rescue typedef(:ulong, :size_t)
9
+
10
+ # memory allocators
11
+ attach_function :malloc, [:size_t], :pointer
12
+ attach_function :free, [:pointer], :void
13
+
14
+ # get a pointer to the free function; used for ZMQ::Message deallocation
15
+ Free = library.find_symbol('free')
16
+
17
+ # memory movers
18
+ attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
19
+ end # module LibC
@@ -0,0 +1,156 @@
1
+ module XS
2
+
3
+ # Wraps the libxs library and attaches to the API functions
4
+ #
5
+ module LibXS
6
+ extend FFI::Library
7
+
8
+ begin
9
+ # bias the library discovery to a path inside the gem first, then
10
+ # to the usual system paths
11
+ inside_gem = File.join(File.dirname(__FILE__), '..', '..', 'ext')
12
+ XS_LIB_PATHS = [
13
+ inside_gem, '/usr/local/lib', '/opt/local/lib', '/usr/local/homebrew/lib', '/usr/lib64'
14
+ ].map{|path| "#{path}/libxs.#{FFI::Platform::LIBSUFFIX}"}
15
+ ffi_lib(XS_LIB_PATHS + %w{libxs})
16
+ rescue LoadError
17
+ STDERR.puts "Unable to load this gem. The libxs library (or DLL) could not be found."
18
+ STDERR.puts "If this is a Windows platform, make sure libxs.dll is on the PATH."
19
+ STDERR.puts "For non-Windows platforms, make sure libxs is located in this search path:"
20
+ STDERR.puts XS_LIB_PATHS.inspect
21
+ exit 255
22
+ end
23
+
24
+ # Size_t not working properly on Windows
25
+ find_type(:size_t) rescue typedef(:ulong, :size_t)
26
+
27
+ # Context and misc api
28
+ #
29
+ # @blocking = true is a hint to FFI that the following (and only the following)
30
+ # function may block, therefore it should release the GIL before calling it.
31
+ # This can aid in situations where the function call will/may block and another
32
+ # thread within the lib may try to call back into the ruby runtime. Failure to
33
+ # release the GIL will result in a hang; the hint *may* allow things to run
34
+ # smoothly for Ruby runtimes hampered by a GIL.
35
+ #
36
+ # This is really only honored by the MRI implementation but it *is* necessary
37
+ # otherwise the runtime hangs (and requires a kill -9 to terminate)
38
+ #
39
+ @blocking = true
40
+ attach_function :xs_errno, [], :int
41
+ @blocking = true
42
+ attach_function :xs_init, [], :pointer
43
+ @blocking = true
44
+ attach_function :xs_setctxopt, [:pointer, :int, :pointer, :int], :int
45
+ @blocking = true
46
+ attach_function :xs_socket, [:pointer, :int], :pointer
47
+ @blocking = true
48
+ attach_function :xs_strerror, [:int], :pointer
49
+ @blocking = true
50
+ attach_function :xs_term, [:pointer], :int
51
+ @blocking = true
52
+ attach_function :xs_version, [:pointer, :pointer, :pointer], :void
53
+
54
+ def self.version
55
+ if @version.nil?
56
+ major = FFI::MemoryPointer.new :int
57
+ minor = FFI::MemoryPointer.new :int
58
+ patch = FFI::MemoryPointer.new :int
59
+ LibXS.xs_version major, minor, patch
60
+ @version = {:major => major.read_int, :minor => minor.read_int, :patch => patch.read_int}
61
+ end
62
+
63
+ @version
64
+ end
65
+
66
+ # Message api
67
+ @blocking = true
68
+ attach_function :xs_msg_close, [:pointer], :int
69
+ @blocking = true
70
+ attach_function :xs_msg_copy, [:pointer, :pointer], :int
71
+ @blocking = true
72
+ attach_function :xs_msg_data, [:pointer], :pointer
73
+ @blocking = true
74
+ attach_function :xs_msg_init, [:pointer], :int
75
+ @blocking = true
76
+ attach_function :xs_msg_init_size, [:pointer, :size_t], :int
77
+ @blocking = true
78
+ attach_function :xs_msg_init_data, [:pointer, :pointer, :size_t, :pointer, :pointer], :int
79
+ @blocking = true
80
+ attach_function :xs_msg_move, [:pointer, :pointer], :int
81
+ @blocking = true
82
+ attach_function :xs_msg_size, [:pointer], :size_t
83
+
84
+ # Used for casting pointers back to the struct
85
+ #
86
+ class Msg < FFI::Struct
87
+ layout :content, :pointer,
88
+ :flags, :uint8,
89
+ :vsm_size, :uint8,
90
+ :vsm_data, [:uint8, 30]
91
+ end # class Msg
92
+
93
+ # Socket api
94
+ @blocking = true
95
+ attach_function :xs_bind, [:pointer, :string], :int
96
+ @blocking = true
97
+ attach_function :xs_connect, [:pointer, :string], :int
98
+ @blocking = true
99
+ attach_function :xs_close, [:pointer], :int
100
+ @blocking = true
101
+ attach_function :xs_getsockopt, [:pointer, :int, :pointer, :pointer], :int
102
+ @blocking = true
103
+ attach_function :xs_recvmsg, [:pointer, :pointer, :int], :int
104
+ @blocking = true
105
+ attach_function :xs_recv, [:pointer, :pointer, :size_t, :int], :int
106
+ @blocking = true
107
+ attach_function :xs_sendmsg, [:pointer, :pointer, :int], :int
108
+ @blocking = true
109
+ attach_function :xs_send, [:pointer, :pointer, :size_t, :int], :int
110
+ @blocking = true
111
+ attach_function :xs_setsockopt, [:pointer, :int, :pointer, :int], :int
112
+
113
+ # Poll api
114
+ @blocking = true
115
+ attach_function :xs_poll, [:pointer, :int, :long], :int
116
+
117
+ module PollItemLayout
118
+ def self.included(base)
119
+ base.class_eval do
120
+ layout :socket, :pointer,
121
+ :fd, :int,
122
+ :events, :short,
123
+ :revents, :short
124
+ end
125
+ end
126
+ end # module PollItemLayout
127
+
128
+ class PollItem < FFI::Struct
129
+ include PollItemLayout
130
+
131
+ def socket() self[:socket]; end
132
+
133
+ def fd() self[:fd]; end
134
+
135
+ def readable?
136
+ (self[:revents] & XS::POLLIN) > 0
137
+ end
138
+
139
+ def writable?
140
+ (self[:revents] & XS::POLLOUT) > 0
141
+ end
142
+
143
+ def both_accessible?
144
+ readable? && writable?
145
+ end
146
+
147
+ def inspect
148
+ "socket [#{socket}], fd [#{fd}], events [#{self[:events]}], revents [#{self[:revents]}]"
149
+ end
150
+
151
+ def to_s; inspect; end
152
+ end # class PollItem
153
+
154
+ end
155
+
156
+ end # module XS
@@ -0,0 +1,156 @@
1
+ module XS
2
+
3
+ # Wraps the libxs library and attaches to the API functions
4
+ #
5
+ module LibXS
6
+ extend FFI::Library
7
+
8
+ begin
9
+ # bias the library discovery to a path inside the gem first, then
10
+ # to the usual system paths
11
+ inside_gem = File.join(File.dirname(__FILE__), '..', '..', 'ext')
12
+ XS_LIB_PATHS = [
13
+ inside_gem, '/usr/local/lib', '/opt/local/lib', '/usr/local/homebrew/lib', '/usr/lib64'
14
+ ].map{|path| "#{path}/libxs.#{FFI::Platform::LIBSUFFIX}"}
15
+ ffi_lib(XS_LIB_PATHS + %w{libxs})
16
+ rescue LoadError
17
+ STDERR.puts "Unable to load this gem. The libxs library (or DLL) could not be found."
18
+ STDERR.puts "If this is a Windows platform, make sure libxs.dll is on the PATH."
19
+ STDERR.puts "For non-Windows platforms, make sure libxs is located in this search path:"
20
+ STDERR.puts XS_LIB_PATHS.inspect
21
+ exit 255
22
+ end
23
+
24
+ # Size_t not working properly on Windows
25
+ find_type(:size_t) rescue typedef(:ulong, :size_t)
26
+
27
+ # Context and misc api
28
+ #
29
+ # @blocking = true is a hint to FFI that the following (and only the following)
30
+ # function may block, therefore it should release the GIL before calling it.
31
+ # This can aid in situations where the function call will/may block and another
32
+ # thread within the lib may try to call back into the ruby runtime. Failure to
33
+ # release the GIL will result in a hang; the hint *may* allow things to run
34
+ # smoothly for Ruby runtimes hampered by a GIL.
35
+ #
36
+ # This is really only honored by the MRI implementation but it *is* necessary
37
+ # otherwise the runtime hangs (and requires a kill -9 to terminate)
38
+ #
39
+ @blocking = true
40
+ attach_function :xs_errno, [], :int
41
+ @blocking = true
42
+ attach_function :xs_init, [:int], :pointer
43
+ @blocking = true
44
+ attach_function :xs_setctxopt, [:pointer, :int, :pointer, :int], :int
45
+ @blocking = true
46
+ attach_function :xs_socket, [:pointer, :int], :pointer
47
+ @blocking = true
48
+ attach_function :xs_strerror, [:int], :pointer
49
+ @blocking = true
50
+ attach_function :xs_term, [:pointer], :int
51
+ @blocking = true
52
+ attach_function :xs_version, [:pointer, :pointer, :pointer], :void
53
+
54
+ def self.version
55
+ if @version.nil?
56
+ major = FFI::MemoryPointer.new :int
57
+ minor = FFI::MemoryPointer.new :int
58
+ patch = FFI::MemoryPointer.new :int
59
+ LibXS.xs_version major, minor, patch
60
+ @version = {:major => major.read_int, :minor => minor.read_int, :patch => patch.read_int}
61
+ end
62
+
63
+ @version
64
+ end
65
+
66
+ # Message api
67
+ @blocking = true
68
+ attach_function :xs_msg_close, [:pointer], :int
69
+ @blocking = true
70
+ attach_function :xs_msg_copy, [:pointer, :pointer], :int
71
+ @blocking = true
72
+ attach_function :xs_msg_data, [:pointer], :pointer
73
+ @blocking = true
74
+ attach_function :xs_msg_init, [:pointer], :int
75
+ @blocking = true
76
+ attach_function :xs_msg_init_size, [:pointer, :size_t], :int
77
+ @blocking = true
78
+ attach_function :xs_msg_init_data, [:pointer, :pointer, :size_t, :pointer, :pointer], :int
79
+ @blocking = true
80
+ attach_function :xs_msg_move, [:pointer, :pointer], :int
81
+ @blocking = true
82
+ attach_function :xs_msg_size, [:pointer], :size_t
83
+
84
+ # Used for casting pointers back to the struct
85
+ #
86
+ class Msg < FFI::Struct
87
+ layout :content, :pointer,
88
+ :flags, :uint8,
89
+ :vsm_size, :uint8,
90
+ :vsm_data, [:uint8, 30]
91
+ end # class Msg
92
+
93
+ # Socket api
94
+ @blocking = true
95
+ attach_function :xs_bind, [:pointer, :string], :int
96
+ @blocking = true
97
+ attach_function :xs_connect, [:pointer, :string], :int
98
+ @blocking = true
99
+ attach_function :xs_close, [:pointer], :int
100
+ @blocking = true
101
+ attach_function :xs_getsockopt, [:pointer, :int, :pointer, :pointer], :int
102
+ @blocking = true
103
+ attach_function :xs_recvmsg, [:pointer, :pointer, :int], :int
104
+ @blocking = true
105
+ attach_function :xs_recv, [:pointer, :pointer, :size_t, :int], :int
106
+ @blocking = true
107
+ attach_function :xs_sendmsg, [:pointer, :pointer, :int], :int
108
+ @blocking = true
109
+ attach_function :xs_send, [:pointer, :pointer, :size_t, :int], :int
110
+ @blocking = true
111
+ attach_function :xs_setsockopt, [:pointer, :int, :pointer, :int], :int
112
+
113
+ # Poll api
114
+ @blocking = true
115
+ attach_function :xs_poll, [:pointer, :int, :long], :int
116
+
117
+ module PollItemLayout
118
+ def self.included(base)
119
+ base.class_eval do
120
+ layout :socket, :pointer,
121
+ :fd, :int,
122
+ :events, :short,
123
+ :revents, :short
124
+ end
125
+ end
126
+ end # module PollItemLayout
127
+
128
+ class PollItem < FFI::Struct
129
+ include PollItemLayout
130
+
131
+ def socket() self[:socket]; end
132
+
133
+ def fd() self[:fd]; end
134
+
135
+ def readable?
136
+ (self[:revents] & XS::POLLIN) > 0
137
+ end
138
+
139
+ def writable?
140
+ (self[:revents] & XS::POLLOUT) > 0
141
+ end
142
+
143
+ def both_accessible?
144
+ readable? && writable?
145
+ end
146
+
147
+ def inspect
148
+ "socket [#{socket}], fd [#{fd}], events [#{self[:events]}], revents [#{self[:revents]}]"
149
+ end
150
+
151
+ def to_s; inspect; end
152
+ end # class PollItem
153
+
154
+ end
155
+
156
+ end # module XS