zmachine 0.2.1 → 0.3.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.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/README.md +1 -0
- data/{echo_client.rb → examples/echo_client.rb} +0 -0
- data/{echo_server.rb → examples/echo_server.rb} +0 -0
- data/lib/zmachine.rb +3 -115
- data/lib/zmachine/acceptor.rb +1 -1
- data/lib/zmachine/channel.rb +38 -5
- data/lib/zmachine/connection.rb +57 -152
- data/lib/zmachine/connection_manager.rb +34 -25
- data/lib/zmachine/hashed_wheel.rb +6 -5
- data/lib/zmachine/jeromq-0.3.2-SNAPSHOT.jar +0 -0
- data/lib/zmachine/reactor.rb +9 -7
- data/lib/zmachine/tcp_channel.rb +13 -40
- data/lib/zmachine/timers.rb +15 -43
- data/lib/zmachine/zmq_channel.rb +52 -60
- data/spec/channel_spec.rb +178 -0
- data/spec/connection_spec.rb +36 -11
- data/spec/hashed_wheel_spec.rb +15 -15
- data/spec/support/echo_mock.rb +32 -0
- data/zmachine.gemspec +1 -1
- metadata +9 -9
- data/lib/zmachine/jeromq-0.3.0-SNAPSHOT.jar +0 -0
- data/spec/tcp_channel_spec.rb +0 -109
- data/spec/zmq_channel_spec.rb +0 -113
@@ -19,7 +19,7 @@ module ZMachine
|
|
19
19
|
|
20
20
|
def idle?
|
21
21
|
@new_connections.size == 0 and
|
22
|
-
@zmq_connections.none? {|c| c.channel.
|
22
|
+
@zmq_connections.none? {|c| c.channel.can_recv? } # see comment in #process
|
23
23
|
end
|
24
24
|
|
25
25
|
def shutdown
|
@@ -30,18 +30,17 @@ module ZMachine
|
|
30
30
|
|
31
31
|
def bind(address, port_or_type, handler, *args, &block)
|
32
32
|
ZMachine.logger.debug("zmachine:connection_manager:#{__method__}", address: address, port_or_type: port_or_type) if ZMachine.debug
|
33
|
-
connection = build_connection(handler, *args
|
34
|
-
connection.bind(address, port_or_type)
|
33
|
+
connection = build_connection(handler, *args)
|
34
|
+
connection.bind(address, port_or_type, &block)
|
35
35
|
@new_connections << connection
|
36
36
|
connection
|
37
37
|
end
|
38
38
|
|
39
39
|
def connect(address, port_or_type, handler, *args, &block)
|
40
40
|
ZMachine.logger.debug("zmachine:connection_manager:#{__method__}", address: address, port_or_type: port_or_type) if ZMachine.debug
|
41
|
-
connection = build_connection(handler, *args
|
42
|
-
connection.connect(address, port_or_type)
|
41
|
+
connection = build_connection(handler, *args)
|
42
|
+
connection.connect(address, port_or_type, &block)
|
43
43
|
@new_connections << connection
|
44
|
-
yield connection if block_given?
|
45
44
|
connection
|
46
45
|
rescue java.nio.channels.UnresolvedAddressException
|
47
46
|
raise ZMachine::ConnectionError.new('unable to resolve server address')
|
@@ -55,26 +54,30 @@ module ZMachine
|
|
55
54
|
process_connection(it.next.attachment)
|
56
55
|
it.remove
|
57
56
|
end
|
58
|
-
# super ugly, but ZMQ only triggers the FD if and only if you
|
59
|
-
# every message from the socket. under load however
|
60
|
-
# new messages in the mailbox between last
|
61
|
-
# causes the FD never to be
|
62
|
-
#
|
57
|
+
# super ugly, but ZMQ only triggers the FD if and only if you
|
58
|
+
# have read every message from the socket. under load however
|
59
|
+
# there will always be new messages in the mailbox between last
|
60
|
+
# recv and next select, which causes the FD never to be
|
61
|
+
# triggered again.
|
62
|
+
# the only mitigation strategy i came up with is iterating over all
|
63
|
+
# channels. performance impact shouldn't be too huge, since ZMQ takes
|
64
|
+
# care of all the multiplexing and we only have a small amount of ZMQ
|
65
|
+
# connections in the reactor
|
63
66
|
@zmq_connections.each do |connection|
|
64
|
-
connection.readable! if connection.channel.
|
67
|
+
connection.readable! if connection.channel.can_recv?
|
65
68
|
end
|
66
69
|
end
|
67
70
|
|
68
71
|
def process_connection(connection)
|
69
72
|
new_connection = connection.process_events
|
70
73
|
@new_connections << new_connection if new_connection
|
71
|
-
rescue IOException
|
72
|
-
close_connection(connection)
|
74
|
+
rescue IOException => e
|
75
|
+
close_connection(connection, e)
|
73
76
|
end
|
74
77
|
|
75
|
-
def close_connection(connection)
|
76
|
-
ZMachine.logger.debug("zmachine:connection_manager:#{__method__}", connection: connection) if ZMachine.debug
|
77
|
-
@unbound_connections << connection
|
78
|
+
def close_connection(connection, reason = nil)
|
79
|
+
ZMachine.logger.debug("zmachine:connection_manager:#{__method__}", connection: connection, reason: reason.inspect) if ZMachine.debug
|
80
|
+
@unbound_connections << [connection, reason]
|
78
81
|
end
|
79
82
|
|
80
83
|
def add_new_connections
|
@@ -83,10 +86,12 @@ module ZMachine
|
|
83
86
|
begin
|
84
87
|
connection.register(@selector)
|
85
88
|
@connections << connection
|
86
|
-
|
89
|
+
if connection.channel.is_a?(ZMQChannel)
|
90
|
+
@zmq_connections << connection
|
91
|
+
connection.connection_completed
|
92
|
+
end
|
87
93
|
rescue ClosedChannelException => e
|
88
|
-
|
89
|
-
@unbound_connections << connection
|
94
|
+
@unbound_connections << [connection, e]
|
90
95
|
end
|
91
96
|
end
|
92
97
|
@new_connections.clear
|
@@ -101,7 +106,11 @@ module ZMachine
|
|
101
106
|
begin
|
102
107
|
@connections.delete(connection)
|
103
108
|
@zmq_connections.delete(connection)
|
104
|
-
connection.unbind
|
109
|
+
if connection.method(:unbind).arity != 0
|
110
|
+
connection.unbind(reason)
|
111
|
+
else
|
112
|
+
connection.unbind
|
113
|
+
end
|
105
114
|
connection.close
|
106
115
|
rescue Exception => e
|
107
116
|
ZMachine.logger.exception(e, "failed to unbind connection") if ZMachine.debug
|
@@ -112,16 +121,16 @@ module ZMachine
|
|
112
121
|
|
113
122
|
private
|
114
123
|
|
115
|
-
def build_connection(handler, *args
|
124
|
+
def build_connection(handler, *args)
|
116
125
|
if handler and handler.is_a?(Class)
|
117
|
-
handler.new(*args
|
126
|
+
handler.new(*args)
|
118
127
|
elsif handler and handler.is_a?(Connection)
|
119
128
|
# already initialized connection on reconnect
|
120
129
|
handler
|
121
130
|
elsif handler
|
122
|
-
connection_from_module(handler).new(*args
|
131
|
+
connection_from_module(handler).new(*args)
|
123
132
|
else
|
124
|
-
Connection.new(*args
|
133
|
+
Connection.new(*args)
|
125
134
|
end
|
126
135
|
end
|
127
136
|
|
@@ -27,13 +27,13 @@ module ZMachine
|
|
27
27
|
|
28
28
|
def initialize(number_of_slots, tick_length, start_time = System.nano_time)
|
29
29
|
@slots = Array.new(number_of_slots) { [] }
|
30
|
-
@tick_length = tick_length *
|
30
|
+
@tick_length = tick_length * 1_000_000_000
|
31
31
|
@last = start_time
|
32
32
|
@current_tick = 0
|
33
33
|
end
|
34
34
|
|
35
35
|
def add(timeout, &block)
|
36
|
-
timeout *=
|
36
|
+
timeout *= 1_000_000_000 # s to ns
|
37
37
|
ticks = timeout / @tick_length
|
38
38
|
slot = (@current_tick + ticks) % @slots.length
|
39
39
|
HashedWheelTimeout.new(System.nano_time + timeout, &block).tap do |hwt|
|
@@ -41,14 +41,15 @@ module ZMachine
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
def reset(time =
|
44
|
+
def reset(time = nil)
|
45
45
|
@slots = Array.new(@slots.length) { [] }
|
46
46
|
@current_tick = 0
|
47
|
-
@last = time
|
47
|
+
@last = time || System.nano_time
|
48
48
|
end
|
49
49
|
|
50
50
|
# returns all timeouts
|
51
|
-
def advance(now =
|
51
|
+
def advance(now = nil)
|
52
|
+
now ||= System.nano_time
|
52
53
|
passed_ticks = (now - @last) / @tick_length
|
53
54
|
result = []
|
54
55
|
begin
|
Binary file
|
data/lib/zmachine/reactor.rb
CHANGED
@@ -40,7 +40,7 @@ module ZMachine
|
|
40
40
|
@next_tick_queue = ConcurrentLinkedQueue.new
|
41
41
|
@running = false
|
42
42
|
@shutdown_hooks = []
|
43
|
-
@wheel = HashedWheel.new(512,
|
43
|
+
@wheel = HashedWheel.new(512, 0.01)
|
44
44
|
end
|
45
45
|
|
46
46
|
def add_shutdown_hook(&block)
|
@@ -53,7 +53,7 @@ module ZMachine
|
|
53
53
|
callback = args.shift || block
|
54
54
|
ZMachine.logger.debug("zmachine:reactor:#{__method__}", interval: interval, callback: callback) if ZMachine.debug
|
55
55
|
return unless callback
|
56
|
-
@wheel.add(
|
56
|
+
@wheel.add(interval, &callback)
|
57
57
|
end
|
58
58
|
|
59
59
|
def bind(server, port_or_type=nil, handler=nil, *args, &block)
|
@@ -62,8 +62,9 @@ module ZMachine
|
|
62
62
|
@connection_manager.bind(server, port_or_type, handler, *args, &block)
|
63
63
|
end
|
64
64
|
|
65
|
-
def close_connection(connection)
|
66
|
-
@connection_manager
|
65
|
+
def close_connection(connection, reason = nil)
|
66
|
+
return true unless @connection_manager
|
67
|
+
@connection_manager.close_connection(connection, reason)
|
67
68
|
end
|
68
69
|
|
69
70
|
def connect(server, port_or_type=nil, handler=nil, *args, &block)
|
@@ -129,9 +130,9 @@ module ZMachine
|
|
129
130
|
def run_reactor
|
130
131
|
ZMachine.logger.debug("zmachine:reactor:#{__method__}") if ZMachine.debug
|
131
132
|
run_deferred_callbacks
|
132
|
-
|
133
|
+
return unless @run_reactor
|
133
134
|
run_timers
|
134
|
-
|
135
|
+
return unless @run_reactor
|
135
136
|
@connection_manager.cleanup
|
136
137
|
if @connection_manager.idle?
|
137
138
|
ZMachine.logger.debug("zmachine:reactor:#{__method__}", select: @heartbeat_interval) if ZMachine.debug
|
@@ -149,6 +150,7 @@ module ZMachine
|
|
149
150
|
|
150
151
|
def stop_event_loop
|
151
152
|
@run_reactor = false
|
153
|
+
@connection_manager.shutdown
|
152
154
|
wakeup
|
153
155
|
end
|
154
156
|
|
@@ -173,7 +175,7 @@ module ZMachine
|
|
173
175
|
def run_timers
|
174
176
|
ZMachine.logger.debug("zmachine:reactor:#{__method__}") if ZMachine.debug
|
175
177
|
@wheel.advance.each do |timeout|
|
176
|
-
ZMachine.logger.
|
178
|
+
ZMachine.logger.info("zmachine:reactor:#{__method__}", callback: timeout.callback) if ZMachine.debug
|
177
179
|
timeout.callback.call
|
178
180
|
end
|
179
181
|
end
|
data/lib/zmachine/tcp_channel.rb
CHANGED
@@ -13,6 +13,7 @@ module ZMachine
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def bind(address, port)
|
16
|
+
ZMachine.logger.debug("zmachine:tcp_channel:#{__method__}", channel: self) if ZMachine.debug
|
16
17
|
address = InetSocketAddress.new(address, port)
|
17
18
|
@socket = ServerSocketChannel.open
|
18
19
|
@socket.configure_blocking(false)
|
@@ -20,10 +21,11 @@ module ZMachine
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def bound?
|
23
|
-
@socket.is_a?(ServerSocketChannel)
|
24
|
+
@socket.is_a?(ServerSocketChannel) && @socket.bound?
|
24
25
|
end
|
25
26
|
|
26
27
|
def accept
|
28
|
+
ZMachine.logger.debug("zmachine:tcp_channel:#{__method__}", channel: self) if ZMachine.debug
|
27
29
|
client_socket = @socket.accept
|
28
30
|
return unless client_socket
|
29
31
|
client_socket.configure_blocking(false)
|
@@ -33,6 +35,7 @@ module ZMachine
|
|
33
35
|
end
|
34
36
|
|
35
37
|
def connect(address, port)
|
38
|
+
ZMachine.logger.debug("zmachine:tcp_channel:#{__method__}", channel: self) if ZMachine.debug
|
36
39
|
address = InetSocketAddress.new(address, port)
|
37
40
|
@socket = SocketChannel.open
|
38
41
|
@socket.configure_blocking(false)
|
@@ -51,9 +54,9 @@ module ZMachine
|
|
51
54
|
end
|
52
55
|
|
53
56
|
def finish_connecting
|
57
|
+
ZMachine.logger.debug("zmachine:tcp_channel:#{__method__}", channel: self) if ZMachine.debug
|
54
58
|
return unless connection_pending?
|
55
|
-
@socket.finish_connect
|
56
|
-
return true
|
59
|
+
@socket.finish_connect
|
57
60
|
end
|
58
61
|
|
59
62
|
def connected?
|
@@ -61,50 +64,20 @@ module ZMachine
|
|
61
64
|
end
|
62
65
|
|
63
66
|
def read_inbound_data
|
67
|
+
ZMachine.logger.debug("zmachine:tcp_channel:#{__method__}", channel: self) if ZMachine.debug
|
64
68
|
buffer = @inbound_buffer
|
65
69
|
buffer.clear
|
66
70
|
raise IOException.new("EOF") if @socket.read(buffer) == -1
|
67
71
|
buffer.flip
|
68
72
|
return if buffer.limit == 0
|
69
|
-
|
73
|
+
data = buffer.array[buffer.position...buffer.limit]
|
74
|
+
data = String.from_java_bytes(data) unless @raw
|
75
|
+
data
|
70
76
|
end
|
71
77
|
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
data = data.to_java_bytes if data.is_a?(String) # EM compat
|
76
|
-
buffer = ByteBuffer.wrap(data)
|
77
|
-
if buffer.has_remaining
|
78
|
-
@outbound_queue << buffer
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def write_outbound_data
|
83
|
-
while can_send?
|
84
|
-
buffer = @outbound_queue.first
|
85
|
-
@socket.write(buffer) if buffer.has_remaining
|
86
|
-
# Did we consume the whole outbound buffer? If yes,
|
87
|
-
# pop it off and keep looping. If no, the outbound network
|
88
|
-
# buffers are full, so break out of here.
|
89
|
-
if buffer.remaining == 0
|
90
|
-
@outbound_queue.shift
|
91
|
-
else
|
92
|
-
break
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
if can_send?
|
97
|
-
# network buffers are full
|
98
|
-
return false
|
99
|
-
end
|
100
|
-
|
101
|
-
close if @close_scheduled
|
102
|
-
return true
|
103
|
-
end
|
104
|
-
|
105
|
-
def close(after_writing = false)
|
106
|
-
super
|
107
|
-
@socket.close unless can_send?
|
78
|
+
def close!
|
79
|
+
ZMachine.logger.debug("zmachine:tcp_channel:#{__method__}", channel: self) if ZMachine.debug
|
80
|
+
@socket.close
|
108
81
|
end
|
109
82
|
|
110
83
|
def closed?
|
data/lib/zmachine/timers.rb
CHANGED
@@ -1,61 +1,33 @@
|
|
1
1
|
module ZMachine
|
2
|
-
# Creates a one-time timer
|
3
|
-
#
|
4
|
-
# timer = ZMachine::Timer.new(5) do
|
5
|
-
# # this will never fire because we cancel it
|
6
|
-
# end
|
7
|
-
# timer.cancel
|
8
|
-
#
|
9
2
|
class Timer
|
10
|
-
# Create a new timer that fires after a given number of seconds
|
11
|
-
def initialize(interval, callback=nil, &block)
|
12
|
-
@signature = ZMachine.add_timer(interval, callback || block)
|
13
|
-
end
|
14
3
|
|
15
|
-
|
16
|
-
def cancel
|
17
|
-
ZMachine.cancel_timer(@signature)
|
18
|
-
end
|
19
|
-
end
|
4
|
+
attr_accessor :interval
|
20
5
|
|
21
|
-
# Creates a periodic timer
|
22
|
-
#
|
23
|
-
# @example
|
24
|
-
# n = 0
|
25
|
-
# timer = ZMachine::PeriodicTimer.new(5) do
|
26
|
-
# puts "the time is #{Time.now}"
|
27
|
-
# timer.cancel if (n+=1) > 5
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
class PeriodicTimer
|
31
|
-
# Create a new periodic timer that executes every interval seconds
|
32
6
|
def initialize(interval, callback=nil, &block)
|
33
7
|
@interval = interval
|
34
|
-
@
|
35
|
-
@cancelled = false
|
36
|
-
@work = method(:fire)
|
8
|
+
@callback = callback || block
|
37
9
|
schedule
|
38
10
|
end
|
39
11
|
|
40
|
-
|
41
|
-
|
42
|
-
@cancelled = true
|
12
|
+
def schedule
|
13
|
+
@timer = ZMachine.add_timer(@interval, method(:fire))
|
43
14
|
end
|
44
15
|
|
45
|
-
|
46
|
-
|
16
|
+
def fire
|
17
|
+
@callback.call
|
18
|
+
end
|
47
19
|
|
48
|
-
|
49
|
-
|
50
|
-
ZMachine.add_timer(@interval, @work)
|
20
|
+
def cancel
|
21
|
+
@timer.cancel
|
51
22
|
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class PeriodicTimer < Timer
|
52
26
|
|
53
|
-
# @private
|
54
27
|
def fire
|
55
|
-
|
56
|
-
|
57
|
-
schedule
|
58
|
-
end
|
28
|
+
super
|
29
|
+
schedule
|
59
30
|
end
|
31
|
+
|
60
32
|
end
|
61
33
|
end
|
data/lib/zmachine/zmq_channel.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
require 'zmachine/jeromq-0.3.
|
1
|
+
require 'zmachine/jeromq-0.3.2-SNAPSHOT.jar'
|
2
|
+
java_import org.zeromq.ZMsg
|
2
3
|
java_import org.zeromq.ZMQ
|
3
4
|
java_import org.zeromq.ZMQException
|
4
5
|
|
@@ -9,35 +10,39 @@ class ZMQ
|
|
9
10
|
class Socket
|
10
11
|
# for performance reason we alias the method here (otherwise it uses reflections all the time!)
|
11
12
|
# super ugly, since we need to dynamically infer the java class of byte[]
|
13
|
+
java_alias :send_byte_buffer, :sendByteBuffer, [Java::JavaNio::ByteBuffer.java_class, Java::int]
|
12
14
|
java_alias :send_byte_array, :send, [[].to_java(:byte).java_class, Java::int]
|
13
15
|
java_alias :recv_byte_array, :recv, [Java::int]
|
16
|
+
|
17
|
+
def write(buffer)
|
18
|
+
bytes = send_byte_buffer(buffer, 0)
|
19
|
+
buffer.position(buffer.position + bytes)
|
20
|
+
end
|
14
21
|
end
|
15
22
|
end
|
16
23
|
|
17
24
|
module ZMachine
|
18
25
|
class ZMQChannel < Channel
|
19
26
|
|
20
|
-
|
21
|
-
super()
|
22
|
-
@socket = ZMachine.context.create_socket(type)
|
23
|
-
@bound = false
|
24
|
-
@connected = false
|
25
|
-
@closed = false
|
26
|
-
end
|
27
|
+
extend Forwardable
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
def
|
32
|
-
|
29
|
+
def_delegator :@socket, :identity
|
30
|
+
def_delegator :@socket, :identity=
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
super
|
34
|
+
@raw = true
|
33
35
|
end
|
34
36
|
|
35
37
|
def selectable_fd
|
36
38
|
@socket.fd
|
37
39
|
end
|
38
40
|
|
39
|
-
def bind(address,
|
41
|
+
def bind(address, type)
|
42
|
+
ZMachine.logger.debug("zmachine:zmq_channel:#{__method__}", channel: self) if ZMachine.debug
|
40
43
|
@bound = true
|
44
|
+
@connected = true
|
45
|
+
@socket = ZMachine.context.create_socket(type)
|
41
46
|
@socket.bind(address)
|
42
47
|
end
|
43
48
|
|
@@ -45,13 +50,26 @@ module ZMachine
|
|
45
50
|
@bound
|
46
51
|
end
|
47
52
|
|
48
|
-
def
|
49
|
-
|
53
|
+
def accept
|
54
|
+
ZMachine.logger.debug("zmachine:zmq_channel:#{__method__}", channel: self) if ZMachine.debug
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def connect(address, type)
|
59
|
+
ZMachine.logger.debug("zmachine:zmq_channel:#{__method__}", channel: self) if ZMachine.debug
|
60
|
+
@connection_pending = true
|
61
|
+
@socket = ZMachine.context.create_socket(type)
|
50
62
|
@socket.connect(address)
|
51
63
|
end
|
52
64
|
|
53
65
|
def connection_pending?
|
54
|
-
|
66
|
+
@connection_pending
|
67
|
+
end
|
68
|
+
|
69
|
+
def finish_connecting
|
70
|
+
ZMachine.logger.debug("zmachine:zmq_channel:#{__method__}", channel: self) if ZMachine.debug
|
71
|
+
return unless connection_pending?
|
72
|
+
@connected = true
|
55
73
|
end
|
56
74
|
|
57
75
|
def connected?
|
@@ -59,71 +77,40 @@ module ZMachine
|
|
59
77
|
end
|
60
78
|
|
61
79
|
def read_inbound_data
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
80
|
+
ZMachine.logger.debug("zmachine:zmq_channel:#{__method__}", channel: self) if ZMachine.debug
|
81
|
+
data = ZMsg.recv_msg(@socket)
|
82
|
+
data = String.from_java_bytes(data.first.data) unless @raw
|
66
83
|
data
|
67
84
|
end
|
68
85
|
|
69
|
-
def send_data(data)
|
70
|
-
parts, last = data[0..-2], data.last
|
71
|
-
parts.each do |part|
|
72
|
-
@socket.send_byte_array(part, ZMQ::SNDMORE | ZMQ::DONTWAIT)
|
73
|
-
end
|
74
|
-
@socket.send_byte_array(last, ZMQ::DONTWAIT)
|
75
|
-
rescue ZMQException
|
76
|
-
@outbound_queue << data
|
77
|
-
end
|
78
|
-
|
79
|
-
# to get around iterating over an array in #send_data we pass message parts
|
80
|
-
# as arguments
|
81
86
|
def send1(a)
|
82
87
|
@socket.send_byte_array(a, ZMQ::DONTWAIT)
|
83
88
|
end
|
84
89
|
|
85
90
|
def send2(a, b)
|
86
|
-
@socket.send_byte_array(a, ZMQ::SNDMORE | ZMQ::DONTWAIT)
|
91
|
+
@socket.send_byte_array(a, ZMQ::SNDMORE | ZMQ::DONTWAIT) and
|
87
92
|
@socket.send_byte_array(b, ZMQ::DONTWAIT)
|
88
93
|
end
|
89
94
|
|
90
95
|
def send3(a, b, c)
|
91
|
-
@socket.send_byte_array(a, ZMQ::SNDMORE | ZMQ::DONTWAIT)
|
92
|
-
@socket.send_byte_array(b, ZMQ::SNDMORE | ZMQ::DONTWAIT)
|
96
|
+
@socket.send_byte_array(a, ZMQ::SNDMORE | ZMQ::DONTWAIT) and
|
97
|
+
@socket.send_byte_array(b, ZMQ::SNDMORE | ZMQ::DONTWAIT) and
|
93
98
|
@socket.send_byte_array(c, ZMQ::DONTWAIT)
|
94
99
|
end
|
95
100
|
|
96
101
|
def send4(a, b, c, d)
|
97
|
-
@socket.send_byte_array(a, ZMQ::SNDMORE | ZMQ::DONTWAIT)
|
98
|
-
@socket.send_byte_array(b, ZMQ::SNDMORE | ZMQ::DONTWAIT)
|
99
|
-
@socket.send_byte_array(c, ZMQ::SNDMORE | ZMQ::DONTWAIT)
|
102
|
+
@socket.send_byte_array(a, ZMQ::SNDMORE | ZMQ::DONTWAIT) and
|
103
|
+
@socket.send_byte_array(b, ZMQ::SNDMORE | ZMQ::DONTWAIT) and
|
104
|
+
@socket.send_byte_array(c, ZMQ::SNDMORE | ZMQ::DONTWAIT) and
|
100
105
|
@socket.send_byte_array(d, ZMQ::DONTWAIT)
|
101
106
|
end
|
102
107
|
|
103
|
-
def
|
104
|
-
|
105
|
-
end
|
106
|
-
|
107
|
-
def can_send?
|
108
|
-
super and (@socket.events & ZMQ::Poller::POLLOUT == ZMQ::Poller::POLLOUT)
|
109
|
-
end
|
110
|
-
|
111
|
-
def write_outbound_data
|
112
|
-
while can_send?
|
113
|
-
data = @outbound_queue.shift
|
114
|
-
send_data(data)
|
115
|
-
end
|
116
|
-
|
117
|
-
close if @close_scheduled
|
118
|
-
return true
|
119
|
-
end
|
120
|
-
|
121
|
-
def close(after_writing = false)
|
122
|
-
super
|
108
|
+
def close!
|
109
|
+
ZMachine.logger.debug("zmachine:zmq_channel:#{__method__}", channel: self) if ZMachine.debug
|
123
110
|
@closed = true
|
124
111
|
@connected = false
|
125
112
|
@bound = false
|
126
|
-
ZMachine.context.destroySocket(@socket)
|
113
|
+
ZMachine.context.destroySocket(@socket)
|
127
114
|
end
|
128
115
|
|
129
116
|
def closed?
|
@@ -134,5 +121,10 @@ module ZMachine
|
|
134
121
|
raise RuntimeError.new("ZMQChannel has no peer")
|
135
122
|
end
|
136
123
|
|
124
|
+
# see comment in ConnectionManager#process
|
125
|
+
def can_recv?
|
126
|
+
@socket.events & ZMQ::Poller::POLLIN == ZMQ::Poller::POLLIN
|
127
|
+
end
|
128
|
+
|
137
129
|
end
|
138
130
|
end
|