ffi-rxs 1.0.0

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.
@@ -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