ffi-rxs 1.1.0 → 1.2.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.
- data/.gitignore +1 -0
- data/CHANGELOG +10 -0
- data/README.textile +13 -6
- data/examples/request.rb +1 -1
- data/ffi-rxs.gemspec +2 -2
- data/lib/ffi-rxs/constants.rb +12 -1
- data/lib/ffi-rxs/context.rb +1 -2
- data/lib/ffi-rxs/libxs.rb +2 -0
- data/lib/ffi-rxs/message.rb +0 -1
- data/lib/ffi-rxs/poll.rb +0 -1
- data/lib/ffi-rxs/socket.rb +19 -4
- data/lib/ffi-rxs/util.rb +22 -27
- data/lib/ffi-rxs/version.rb +1 -1
- data/spec/context_spec.rb +2 -6
- data/spec/message_spec.rb +2 -0
- data/spec/multipart_spec.rb +2 -0
- data/spec/nonblocking_recv_spec.rb +1 -0
- data/spec/poll_spec.rb +1 -1
- data/spec/pushpull_spec.rb +3 -2
- data/spec/reqrep_spec.rb +1 -0
- data/spec/socket_spec.rb +46 -9
- data/spec/spec_helper.rb +3 -2
- metadata +26 -24
- data/lib/ffi-rxs/constants.rb~ +0 -100
- data/lib/ffi-rxs/context.rb~ +0 -155
- data/lib/ffi-rxs/device.rb~ +0 -28
- data/lib/ffi-rxs/exceptions.rb~ +0 -47
- data/lib/ffi-rxs/libc.rb~ +0 -19
- data/lib/ffi-rxs/libxs.rb~ +0 -156
- data/lib/ffi-rxs/message.rb~ +0 -282
- data/lib/ffi-rxs/poll.rb~ +0 -212
- data/lib/ffi-rxs/poll_items.rb~ +0 -120
- data/lib/ffi-rxs/socket.rb~ +0 -659
- data/lib/ffi-rxs/util.rb~ +0 -105
- data/lib/ffi-rxs/version.rb~ +0 -3
data/lib/ffi-rxs/constants.rb~
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
module XS
|
2
|
-
# Set up all of the constants
|
3
|
-
|
4
|
-
# Socket types
|
5
|
-
PAIR = 0
|
6
|
-
PUB = 1
|
7
|
-
SUB = 2
|
8
|
-
REQ = 3
|
9
|
-
REP = 4
|
10
|
-
XREQ = 5
|
11
|
-
XREP = 6
|
12
|
-
PULL = 7
|
13
|
-
PUSH = 8
|
14
|
-
XPUB = 9
|
15
|
-
XSUB = 10
|
16
|
-
DEALER = XREQ
|
17
|
-
ROUTER = XREP
|
18
|
-
|
19
|
-
SocketTypeNameMap = {
|
20
|
-
PAIR => "PAIR",
|
21
|
-
PUB => "PUB",
|
22
|
-
SUB => "SUB",
|
23
|
-
REQ => "REQ",
|
24
|
-
REP => "REP",
|
25
|
-
PULL => "PULL",
|
26
|
-
PUSH => "PUSH",
|
27
|
-
XREQ => "XREQ",
|
28
|
-
XREP => "XREP",
|
29
|
-
ROUTER => "ROUTER",
|
30
|
-
DEALER => "DEALER",
|
31
|
-
XPUB => "XPUB",
|
32
|
-
XSUB => "XSUB"
|
33
|
-
}
|
34
|
-
|
35
|
-
# Socket options
|
36
|
-
AFFINITY = 4
|
37
|
-
IDENTITY = 5
|
38
|
-
SUBSCRIBE = 6
|
39
|
-
UNSUBSCRIBE = 7
|
40
|
-
RATE = 8
|
41
|
-
RECOVERY_IVL = 9
|
42
|
-
SNDBUF = 11
|
43
|
-
RCVBUF = 12
|
44
|
-
RCVMORE = 13
|
45
|
-
FD = 14
|
46
|
-
EVENTS = 15
|
47
|
-
TYPE = 16
|
48
|
-
LINGER = 17
|
49
|
-
RECONNECT_IVL = 18
|
50
|
-
BACKLOG = 19
|
51
|
-
RECONNECT_IVL_MAX = 21
|
52
|
-
MAXMSGSIZE = 22
|
53
|
-
SNDHWM = 23
|
54
|
-
RCVHWM = 24
|
55
|
-
MULTICAST_HOPS = 25
|
56
|
-
RCVTIMEO = 27
|
57
|
-
SNDTIMEO = 28
|
58
|
-
|
59
|
-
# Send/recv options
|
60
|
-
DONTWAIT = 1
|
61
|
-
SNDMORE = 2
|
62
|
-
SNDLABEL = 4
|
63
|
-
NonBlocking = DONTWAIT
|
64
|
-
|
65
|
-
# I/O multiplexing
|
66
|
-
|
67
|
-
POLL = 1
|
68
|
-
POLLIN = 1
|
69
|
-
POLLOUT = 2
|
70
|
-
POLLERR = 4
|
71
|
-
|
72
|
-
# Socket errors
|
73
|
-
EAGAIN = Errno::EAGAIN::Errno
|
74
|
-
EFAULT = Errno::EFAULT::Errno
|
75
|
-
EINVAL = Errno::EINVAL::Errno
|
76
|
-
EMFILE = Errno::EMFILE::Errno
|
77
|
-
ENOMEM = Errno::ENOMEM::Errno
|
78
|
-
ENODEV = Errno::ENODEV::Errno
|
79
|
-
|
80
|
-
# XS errors
|
81
|
-
HAUSNUMERO = 156384712
|
82
|
-
EMTHREAD = (HAUSNUMERO + 50)
|
83
|
-
EFSM = (HAUSNUMERO + 51)
|
84
|
-
ENOCOMPATPROTO = (HAUSNUMERO + 52)
|
85
|
-
ETERM = (HAUSNUMERO + 53)
|
86
|
-
|
87
|
-
# Rescue unknown constants and use the Crossroads defined values
|
88
|
-
# Usually only happens on Windows though some don't resolve on
|
89
|
-
# OSX too (ENOTSUP)
|
90
|
-
ENOTSUP = Errno::ENOTSUP::Errno rescue (HAUSNUMERO + 1)
|
91
|
-
EPROTONOSUPPORT = Errno::EPROTONOSUPPORT::Errno rescue (HAUSNUMERO + 2)
|
92
|
-
ENOBUFS = Errno::ENOBUFS::Errno rescue (HAUSNUMERO + 3)
|
93
|
-
ENETDOWN = Errno::ENETDOWN::Errno rescue (HAUSNUMERO + 4)
|
94
|
-
EADDRINUSE = Errno::EADDRINUSE::Errno rescue (HAUSNUMERO + 5)
|
95
|
-
EADDRNOTAVAIL = Errno::EADDRNOTAVAIL::Errno rescue (HAUSNUMERO + 6)
|
96
|
-
ECONNREFUSED = Errno::ECONNREFUSED::Errno rescue (HAUSNUMERO + 7)
|
97
|
-
EINPROGRESS = Errno::EINPROGRESS::Errno rescue (HAUSNUMERO + 8)
|
98
|
-
ENOTSOCK = Errno::ENOTSOCK::Errno rescue (HAUSNUMERO + 9)
|
99
|
-
EINTR = Errno::EINTR::Errno rescue (HAUSNUMERO + 10)
|
100
|
-
end # module XS
|
data/lib/ffi-rxs/context.rb~
DELETED
@@ -1,155 +0,0 @@
|
|
1
|
-
|
2
|
-
module XS
|
3
|
-
|
4
|
-
|
5
|
-
# Recommended to use the default for +io_threads+
|
6
|
-
# since most programs will not saturate I/O.
|
7
|
-
#
|
8
|
-
# The rule of thumb is to make +io_threads+ equal to the number
|
9
|
-
# gigabits per second that the application will produce.
|
10
|
-
#
|
11
|
-
# The +io_threads+ number specifies the size of the thread pool
|
12
|
-
# allocated by 0mq for processing incoming/outgoing messages.
|
13
|
-
#
|
14
|
-
# Returns a context object when allocation succeeds. It's necessary
|
15
|
-
# for passing to the
|
16
|
-
# #Socket constructor when allocating new sockets. All sockets
|
17
|
-
# live within a context.
|
18
|
-
#
|
19
|
-
# Also, Sockets should *only* be accessed from the thread where they
|
20
|
-
# were first created. Do *not* pass sockets between threads; pass
|
21
|
-
# in the context and allocate a new socket per thread. If you must
|
22
|
-
# use threads, then make sure to execute a full memory barrier (e.g.
|
23
|
-
# mutex) as you pass a socket from one thread to the next.
|
24
|
-
#
|
25
|
-
# To connect sockets between contexts, use +inproc+ or +ipc+
|
26
|
-
# transport and set up a Crossroads socket between them. This is also the
|
27
|
-
# recommended technique for allowing sockets to communicate between
|
28
|
-
# threads.
|
29
|
-
#
|
30
|
-
# context = XS::Context.create
|
31
|
-
# if context
|
32
|
-
# socket = context.socket(XS::REQ)
|
33
|
-
# if socket
|
34
|
-
# ...
|
35
|
-
# else
|
36
|
-
# STDERR.puts "Socket allocation failed"
|
37
|
-
# end
|
38
|
-
# else
|
39
|
-
# STDERR.puts "Context allocation failed"
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
#
|
43
|
-
class Context
|
44
|
-
include XS::Util
|
45
|
-
|
46
|
-
attr_reader :context, :pointer
|
47
|
-
|
48
|
-
def self.create
|
49
|
-
new() rescue nil
|
50
|
-
end
|
51
|
-
|
52
|
-
# Use the factory method Context#create to make contexts.
|
53
|
-
#
|
54
|
-
def initialize
|
55
|
-
@sockets = []
|
56
|
-
@context = LibXS.xs_init()
|
57
|
-
@pointer = @context
|
58
|
-
error_check 'xs_init', (@context.nil? || @context.null?) ? -1 : 0
|
59
|
-
|
60
|
-
define_finalizer
|
61
|
-
end
|
62
|
-
|
63
|
-
# Set options on this context.
|
64
|
-
#
|
65
|
-
# Context options take effect only if set with setctxopt() prior to
|
66
|
-
# creating the first socket in a given context with socket().
|
67
|
-
#
|
68
|
-
# Valid +name+ values that take a numeric +value+ are:
|
69
|
-
# XS::IO_THREADS
|
70
|
-
# XS::MAX_SOCKETS
|
71
|
-
#
|
72
|
-
# Returns 0 when the operation completed successfully.
|
73
|
-
# Returns -1 when this operation failed.
|
74
|
-
#
|
75
|
-
# With a -1 return code, the user must check XS.errno to determine the
|
76
|
-
# cause.
|
77
|
-
#
|
78
|
-
# rc = context.setctxopt(XS::IO_THREADS, 10)
|
79
|
-
# XS::Util.resultcode_ok?(rc) ? puts("succeeded") : puts("failed")
|
80
|
-
#
|
81
|
-
def setctxopt name, value, length = nil
|
82
|
-
#if (name == XS::IO_THREADS) || (name == XS::MAX_SOCKETS)
|
83
|
-
length = 4
|
84
|
-
pointer = LibC.malloc length
|
85
|
-
pointer.write_int value
|
86
|
-
#end
|
87
|
-
|
88
|
-
rc = LibXS.xs_setctxopt @context, name, pointer, length
|
89
|
-
LibC.free(pointer) unless pointer.nil? || pointer.null?
|
90
|
-
rc
|
91
|
-
end
|
92
|
-
|
93
|
-
# Call to release the context and any remaining data associated
|
94
|
-
# with past sockets. This will close any sockets that remain
|
95
|
-
# open; further calls to those sockets will return -1 to indicate
|
96
|
-
# the operation failed.
|
97
|
-
#
|
98
|
-
# Returns 0 for success, -1 for failure.
|
99
|
-
#
|
100
|
-
def terminate
|
101
|
-
unless @context.nil? || @context.null?
|
102
|
-
remove_finalizer
|
103
|
-
rc = LibXS.xs_term @context
|
104
|
-
@context = nil
|
105
|
-
@sockets = nil
|
106
|
-
rc
|
107
|
-
else
|
108
|
-
0
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
# Short-cut to allocate a socket for a specific context.
|
113
|
-
#
|
114
|
-
# Takes several +type+ values:
|
115
|
-
# #XS::REQ
|
116
|
-
# #XS::REP
|
117
|
-
# #XS::PUB
|
118
|
-
# #XS::SUB
|
119
|
-
# #XS::PAIR
|
120
|
-
# #XS::PULL
|
121
|
-
# #XS::PUSH
|
122
|
-
# #XS::DEALER
|
123
|
-
# #XS::ROUTER
|
124
|
-
#
|
125
|
-
# Returns a #XS::Socket when the allocation succeeds, nil
|
126
|
-
# if it fails.
|
127
|
-
#
|
128
|
-
def socket type
|
129
|
-
sock = nil
|
130
|
-
begin
|
131
|
-
sock = Socket.new @context, type
|
132
|
-
rescue ContextError => e
|
133
|
-
sock = nil
|
134
|
-
end
|
135
|
-
|
136
|
-
sock
|
137
|
-
end
|
138
|
-
|
139
|
-
|
140
|
-
private
|
141
|
-
|
142
|
-
def define_finalizer
|
143
|
-
ObjectSpace.define_finalizer(self, self.class.close(@context))
|
144
|
-
end
|
145
|
-
|
146
|
-
def remove_finalizer
|
147
|
-
ObjectSpace.undefine_finalizer self
|
148
|
-
end
|
149
|
-
|
150
|
-
def self.close context
|
151
|
-
Proc.new { LibXS.xs_term context unless context.null? }
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
end # module XS
|
data/lib/ffi-rxs/device.rb~
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
module ZMQ
|
2
|
-
if LibZMQ.version2?
|
3
|
-
class Device
|
4
|
-
attr_reader :device
|
5
|
-
|
6
|
-
def self.create(device_type, frontend, backend)
|
7
|
-
dev = nil
|
8
|
-
begin
|
9
|
-
dev = new device_type, frontend, backend
|
10
|
-
rescue ArgumentError
|
11
|
-
dev = nil
|
12
|
-
end
|
13
|
-
|
14
|
-
dev
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize(device_type,frontend,backend)
|
18
|
-
[["frontend", frontend],["backend", backend]].each do |name,socket|
|
19
|
-
unless socket.is_a?(ZMQ::Socket)
|
20
|
-
raise ArgumentError, "Expected a ZMQ::Socket, not a #{socket.class} as the #{name}"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
LibZMQ.zmq_device(device_type, frontend.socket, backend.socket)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
data/lib/ffi-rxs/exceptions.rb~
DELETED
@@ -1,47 +0,0 @@
|
|
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
|
data/lib/ffi-rxs/libc.rb~
DELETED
@@ -1,19 +0,0 @@
|
|
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
|
data/lib/ffi-rxs/libxs.rb~
DELETED
@@ -1,156 +0,0 @@
|
|
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
|