cztop 0.14.1 → 1.1.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/coverage.yml +20 -0
- data/.github/workflows/draft_api.yml +27 -0
- data/.github/workflows/stable_api.yml +26 -0
- data/.rubocop.yml +175 -0
- data/CHANGES.md +9 -4
- data/Gemfile +3 -7
- data/README.md +19 -58
- data/ci/install-libczmq +22 -0
- data/ci/install-libzmq +22 -0
- data/cztop.gemspec +12 -13
- data/lib/cztop/actor.rb +55 -26
- data/lib/cztop/authenticator.rb +18 -9
- data/lib/cztop/beacon.rb +22 -10
- data/lib/cztop/cert_store.rb +8 -2
- data/lib/cztop/certificate.rb +47 -18
- data/lib/cztop/config/comments.rb +14 -3
- data/lib/cztop/config/serialization.rb +25 -5
- data/lib/cztop/config/traversing.rb +44 -13
- data/lib/cztop/config.rb +23 -9
- data/lib/cztop/frame.rb +23 -10
- data/lib/cztop/has_ffi_delegate.rb +11 -1
- data/lib/cztop/message/frames.rb +16 -2
- data/lib/cztop/message.rb +36 -22
- data/lib/cztop/metadata.rb +35 -24
- data/lib/cztop/monitor.rb +14 -5
- data/lib/cztop/poller/aggregated.rb +31 -15
- data/lib/cztop/poller/zmq.rb +25 -22
- data/lib/cztop/poller/zpoller.rb +18 -6
- data/lib/cztop/poller.rb +43 -18
- data/lib/cztop/polymorphic_zsock_methods.rb +6 -1
- data/lib/cztop/proxy.rb +34 -19
- data/lib/cztop/send_receive_methods.rb +5 -1
- data/lib/cztop/socket/types.rb +128 -22
- data/lib/cztop/socket.rb +23 -18
- data/lib/cztop/version.rb +5 -1
- data/lib/cztop/z85/padded.rb +12 -3
- data/lib/cztop/z85/pipe.rb +40 -17
- data/lib/cztop/z85.rb +17 -6
- data/lib/cztop/zap.rb +57 -32
- data/lib/cztop/zsock_options.rb +155 -122
- data/lib/cztop.rb +2 -1
- metadata +25 -90
- data/.gitlab-ci.yml +0 -32
- data/Guardfile +0 -61
- data/Procfile +0 -3
- data/ci-scripts/install-deps +0 -8
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module CZTop
|
2
4
|
# This is a poller which is able to provide a list of readable and a list
|
3
5
|
# of writable sockets. This is useful for when you need to process socket
|
@@ -37,31 +39,37 @@ module CZTop
|
|
37
39
|
# @return [CZTop::Poller.new] the associated (regular) poller
|
38
40
|
attr_reader :poller
|
39
41
|
|
42
|
+
|
40
43
|
# @return [Array<CZTop::Socket>] readable sockets
|
41
44
|
attr_reader :readables
|
42
45
|
|
46
|
+
|
43
47
|
# @return [Array<CZTop::Socket>] writable sockets
|
44
48
|
attr_reader :writables
|
45
49
|
|
50
|
+
|
46
51
|
extend Forwardable
|
52
|
+
|
47
53
|
def_delegators :@poller,
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
54
|
+
:add,
|
55
|
+
:add_reader,
|
56
|
+
:add_writer,
|
57
|
+
:modify,
|
58
|
+
:remove,
|
59
|
+
:remove_reader,
|
60
|
+
:remove_writer,
|
61
|
+
:sockets
|
62
|
+
|
56
63
|
|
57
64
|
# Initializes the aggregated poller.
|
58
65
|
# @param poller [CZTop::Poller] the wrapped poller
|
59
66
|
def initialize(poller = CZTop::Poller.new)
|
60
67
|
@readables = []
|
61
68
|
@writables = []
|
62
|
-
@poller
|
69
|
+
@poller = poller
|
63
70
|
end
|
64
71
|
|
72
|
+
|
65
73
|
# Forgets all previous event information (which sockets are
|
66
74
|
# readable/writable) and waits for events anew. After getting the first
|
67
75
|
# event, {CZTop::Poller#wait} is called again with a zero-timeout to get
|
@@ -76,26 +84,29 @@ module CZTop
|
|
76
84
|
# or -1 to wait indefinitely
|
77
85
|
# @return [Boolean] whether there have been any events
|
78
86
|
def wait(timeout = -1)
|
79
|
-
@readables
|
80
|
-
@writables
|
87
|
+
@readables = []
|
88
|
+
@writables = []
|
81
89
|
@event_masks = {}
|
82
90
|
|
83
|
-
if event = @poller.wait(timeout)
|
91
|
+
if (event = @poller.wait(timeout))
|
84
92
|
extract(event)
|
85
93
|
|
86
94
|
# get all other pending events, if any, but no more blocking
|
87
|
-
while event = @poller.wait
|
95
|
+
while (event = @poller.wait 0)
|
88
96
|
extract(event)
|
89
97
|
end
|
90
98
|
|
91
99
|
restore_event_masks
|
92
100
|
return true
|
93
101
|
end
|
94
|
-
|
102
|
+
|
103
|
+
false
|
95
104
|
end
|
96
105
|
|
106
|
+
|
97
107
|
private
|
98
108
|
|
109
|
+
|
99
110
|
# Extracts the event information, adds the socket to the correct list(s)
|
100
111
|
# and modifies the socket's event mask for the socket to not turn up
|
101
112
|
# again during the next call(s) to {CZTop::Poller#wait} within {#wait}.
|
@@ -103,24 +114,29 @@ module CZTop
|
|
103
114
|
# @param event [CZTop::Poller::Event]
|
104
115
|
# @return [void]
|
105
116
|
def extract(event)
|
106
|
-
event_mask
|
117
|
+
event_mask = poller.event_mask_for_socket(event.socket)
|
107
118
|
@event_masks[event.socket] = event_mask
|
119
|
+
|
108
120
|
if event.readable?
|
109
121
|
@readables << event.socket
|
110
122
|
event_mask &= 0xFFFF ^ CZTop::Poller::ZMQ::POLLIN
|
111
123
|
end
|
124
|
+
|
112
125
|
if event.writable?
|
113
126
|
@writables << event.socket
|
114
127
|
event_mask &= 0xFFFF ^ CZTop::Poller::ZMQ::POLLOUT
|
115
128
|
end
|
129
|
+
|
116
130
|
poller.modify(event.socket, event_mask)
|
117
131
|
end
|
118
132
|
|
133
|
+
|
119
134
|
# Restores the event mask for all registered sockets to the state they
|
120
135
|
# were before the call to {#wait}.
|
121
136
|
# @return [void]
|
122
137
|
def restore_event_masks
|
123
138
|
@event_masks.each { |socket, mask| poller.modify(socket, mask) }
|
124
139
|
end
|
140
|
+
|
125
141
|
end
|
126
142
|
end
|
data/lib/cztop/poller/zmq.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module CZTop
|
3
4
|
# CZTop's interface to the low-level +zmq_poller_*()+ functions.
|
4
5
|
module Poller::ZMQ
|
5
6
|
|
@@ -8,9 +9,9 @@ module CZTop
|
|
8
9
|
POLLERR = 4
|
9
10
|
|
10
11
|
extend ::FFI::Library
|
11
|
-
lib_name
|
12
|
-
lib_dirs
|
13
|
-
lib_dirs
|
12
|
+
lib_name = 'libzmq'
|
13
|
+
lib_dirs = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
|
14
|
+
lib_dirs = [*ENV['LIBZMQ_PATH'].split(':'), *lib_dirs] if ENV['LIBZMQ_PATH']
|
14
15
|
lib_paths = lib_dirs.map { |path| "#{path}/#{lib_name}.#{::FFI::Platform::LIBSUFFIX}" }
|
15
16
|
ffi_lib lib_paths + [lib_name]
|
16
17
|
|
@@ -24,6 +25,7 @@ module CZTop
|
|
24
25
|
# short events;
|
25
26
|
# } zmq_poller_event_t;
|
26
27
|
class PollerEvent < FFI::Struct
|
28
|
+
|
27
29
|
layout :socket, :pointer,
|
28
30
|
:fd, :int,
|
29
31
|
:user_data, :pointer,
|
@@ -31,21 +33,23 @@ module CZTop
|
|
31
33
|
|
32
34
|
# @return [Boolean] whether the socket is readable
|
33
35
|
def readable?
|
34
|
-
(self[:events] & POLLIN)
|
36
|
+
(self[:events] & POLLIN).positive?
|
35
37
|
end
|
36
38
|
|
39
|
+
|
37
40
|
# @return [Boolean] whether the socket is writable
|
38
41
|
def writable?
|
39
|
-
(self[:events] & POLLOUT)
|
42
|
+
(self[:events] & POLLOUT).positive?
|
40
43
|
end
|
44
|
+
|
41
45
|
end
|
42
46
|
|
43
|
-
#ZMQ_EXPORT void *zmq_poller_new (void);
|
44
|
-
#ZMQ_EXPORT int zmq_poller_destroy (void **poller_p);
|
45
|
-
#ZMQ_EXPORT int zmq_poller_add (void *poller, void *socket, void *user_data, short events);
|
46
|
-
#ZMQ_EXPORT int zmq_poller_modify (void *poller, void *socket, short events);
|
47
|
-
#ZMQ_EXPORT int zmq_poller_remove (void *poller, void *socket);
|
48
|
-
#ZMQ_EXPORT int zmq_poller_wait (void *poller, zmq_poller_event_t *event, long timeout);
|
47
|
+
# ZMQ_EXPORT void *zmq_poller_new (void);
|
48
|
+
# ZMQ_EXPORT int zmq_poller_destroy (void **poller_p);
|
49
|
+
# ZMQ_EXPORT int zmq_poller_add (void *poller, void *socket, void *user_data, short events);
|
50
|
+
# ZMQ_EXPORT int zmq_poller_modify (void *poller, void *socket, short events);
|
51
|
+
# ZMQ_EXPORT int zmq_poller_remove (void *poller, void *socket);
|
52
|
+
# ZMQ_EXPORT int zmq_poller_wait (void *poller, zmq_poller_event_t *event, long timeout);
|
49
53
|
|
50
54
|
# Gracefully attaches a function. If it's not available, this creates
|
51
55
|
# a placeholder class method which, when called, simply raises
|
@@ -53,27 +57,26 @@ module CZTop
|
|
53
57
|
def self.attach_function(function_nickname, function_name, *args)
|
54
58
|
super
|
55
59
|
rescue ::FFI::NotFoundError
|
56
|
-
if $VERBOSE || $DEBUG
|
57
|
-
warn "CZTop: The ZMQ function #{function_name}() is not available. Don't use CZTop::Poller."
|
58
|
-
end
|
60
|
+
warn "CZTop: The ZMQ function #{function_name}() is not available. Don't use CZTop::Poller." if $VERBOSE || $DEBUG
|
59
61
|
define_singleton_method(function_nickname) do |*|
|
60
|
-
raise NotImplementedError,
|
62
|
+
raise NotImplementedError, 'compile ZMQ with --enable-drafts'
|
61
63
|
end
|
62
64
|
end
|
63
65
|
|
64
66
|
opts = {
|
65
|
-
blocking: true
|
67
|
+
blocking: true # only necessary on MRI to deal with the GIL.
|
66
68
|
}
|
67
69
|
attach_function :poller_new, :zmq_poller_new, [], :pointer, **opts
|
68
70
|
attach_function :poller_destroy, :zmq_poller_destroy,
|
69
|
-
|
71
|
+
[:pointer], :int, **opts
|
70
72
|
attach_function :poller_add, :zmq_poller_add,
|
71
|
-
|
73
|
+
%i[pointer pointer pointer short], :int, **opts
|
72
74
|
attach_function :poller_modify, :zmq_poller_modify,
|
73
|
-
|
75
|
+
%i[pointer pointer short], :int, **opts
|
74
76
|
attach_function :poller_remove, :zmq_poller_remove,
|
75
|
-
|
77
|
+
%i[pointer pointer], :int, **opts
|
76
78
|
attach_function :poller_wait, :zmq_poller_wait,
|
77
|
-
|
79
|
+
%i[pointer pointer long], :int, **opts
|
80
|
+
|
78
81
|
end
|
79
82
|
end
|
data/lib/cztop/poller/zpoller.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module CZTop
|
2
4
|
# This is the trivial poller based on zpoller. It only supports polling
|
3
5
|
# for readability, but it also supports doing that on CLIENT/SERVER sockets,
|
@@ -5,6 +7,7 @@ module CZTop
|
|
5
7
|
#
|
6
8
|
# @see http://api.zeromq.org/czmq3-0:zpoller
|
7
9
|
class Poller::ZPoller
|
10
|
+
|
8
11
|
include HasFFIDelegate
|
9
12
|
extend CZTop::HasFFIDelegate::ClassMethods
|
10
13
|
include ::CZMQ::FFI
|
@@ -14,24 +17,26 @@ module CZTop
|
|
14
17
|
# @param readers [Socket, Actor] any additional sockets to poll for input
|
15
18
|
def initialize(reader, *readers)
|
16
19
|
@sockets = {} # to keep references and return same instances
|
17
|
-
ptr
|
18
|
-
|
19
|
-
|
20
|
+
ptr = Zpoller.new(reader,
|
21
|
+
*readers.flat_map { |r| [:pointer, r] },
|
22
|
+
:pointer, nil)
|
20
23
|
attach_ffi_delegate(ptr)
|
21
24
|
remember_socket(reader)
|
22
25
|
readers.each { |r| remember_socket(r) }
|
23
26
|
end
|
24
27
|
|
28
|
+
|
25
29
|
# Adds another reader socket to the poller.
|
26
30
|
# @param reader [Socket, Actor] socket to poll for input
|
27
31
|
# @return [void]
|
28
32
|
# @raise [SystemCallError] if this fails
|
29
33
|
def add(reader)
|
30
34
|
rc = ffi_delegate.add(reader)
|
31
|
-
raise_zmq_err(
|
35
|
+
raise_zmq_err(format('unable to add socket %p', reader)) if rc == -1
|
32
36
|
remember_socket(reader)
|
33
37
|
end
|
34
38
|
|
39
|
+
|
35
40
|
# Removes a reader socket from the poller.
|
36
41
|
# @param reader [Socket, Actor] socket to remove
|
37
42
|
# @return [void]
|
@@ -40,10 +45,11 @@ module CZTop
|
|
40
45
|
# @raise [SystemCallError] if this fails for another reason
|
41
46
|
def remove(reader)
|
42
47
|
rc = ffi_delegate.remove(reader)
|
43
|
-
raise_zmq_err(
|
48
|
+
raise_zmq_err(format('unable to remove socket %p', reader)) if rc == -1
|
44
49
|
forget_socket(reader)
|
45
50
|
end
|
46
51
|
|
52
|
+
|
47
53
|
# Waits and returns the first socket that becomes readable.
|
48
54
|
# @param timeout [Integer] how long to wait in ms, or 0 to avoid
|
49
55
|
# blocking, or -1 to wait indefinitely
|
@@ -54,11 +60,13 @@ module CZTop
|
|
54
60
|
ptr = ffi_delegate.wait(timeout)
|
55
61
|
if ptr.null?
|
56
62
|
raise Interrupt if ffi_delegate.terminated
|
63
|
+
|
57
64
|
return nil
|
58
65
|
end
|
59
|
-
|
66
|
+
socket_by_ptr(ptr)
|
60
67
|
end
|
61
68
|
|
69
|
+
|
62
70
|
# Tells the zpoller to ignore interrupts. By default, {#wait} will return
|
63
71
|
# immediately if it detects an interrupt (when +zsys_interrupted+ is set
|
64
72
|
# to something other than zero). Calling this method will supress this
|
@@ -68,6 +76,7 @@ module CZTop
|
|
68
76
|
ffi_delegate.ignore_interrupts
|
69
77
|
end
|
70
78
|
|
79
|
+
|
71
80
|
# By default the poller stops if the process receives a SIGINT or SIGTERM
|
72
81
|
# signal. This makes it impossible to shut-down message based architectures
|
73
82
|
# like zactors. This method lets you switch off break handling. The default
|
@@ -91,6 +100,7 @@ module CZTop
|
|
91
100
|
@sockets[socket.to_ptr.to_i] = socket
|
92
101
|
end
|
93
102
|
|
103
|
+
|
94
104
|
# Forgets the socket because it has been removed from the poller.
|
95
105
|
# @param socket [Socket, Actor] the socket instance to forget
|
96
106
|
# @return [void]
|
@@ -98,6 +108,7 @@ module CZTop
|
|
98
108
|
@sockets.delete(socket.to_ptr.to_i)
|
99
109
|
end
|
100
110
|
|
111
|
+
|
101
112
|
# Gets the previously remembered socket associated to the given pointer.
|
102
113
|
# @param ptr [FFI::Pointer] the pointer to a socket
|
103
114
|
# @return [Socket, Actor] the socket associated to the given pointer
|
@@ -109,5 +120,6 @@ module CZTop
|
|
109
120
|
# it ever returns a wrong pointer.
|
110
121
|
raise_zmq_err("no socket known for pointer #{ptr.inspect}")
|
111
122
|
end
|
123
|
+
|
112
124
|
end
|
113
125
|
end
|
data/lib/cztop/poller.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module CZTop
|
2
4
|
# A non-trivial socket poller.
|
3
5
|
#
|
@@ -9,23 +11,25 @@ module CZTop
|
|
9
11
|
# * +zpoller+ can only poll for readability
|
10
12
|
#
|
11
13
|
class Poller
|
14
|
+
|
12
15
|
include ::CZMQ::FFI
|
13
16
|
|
14
17
|
# @param readers [Socket, Actor] sockets to poll for input
|
15
18
|
def initialize(*readers)
|
16
|
-
@sockets
|
17
|
-
@events
|
19
|
+
@sockets = {} # needed to return the same socket objects
|
20
|
+
@events = {} # event masks for each socket
|
18
21
|
@poller_ptr = ZMQ.poller_new
|
19
22
|
ObjectSpace.define_finalizer(@poller_ptr,
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
proc do
|
24
|
+
ptr_ptr = ::FFI::MemoryPointer.new :pointer
|
25
|
+
ptr_ptr.write_pointer(@poller_ptr)
|
26
|
+
ZMQ.poller_destroy(ptr_ptr)
|
27
|
+
end)
|
25
28
|
@event_ptr = FFI::MemoryPointer.new(ZMQ::PollerEvent)
|
26
29
|
readers.each { |r| add_reader(r) }
|
27
30
|
end
|
28
31
|
|
32
|
+
|
29
33
|
# Adds a socket to be polled for readability.
|
30
34
|
# @param socket [Socket, Actor] the socket
|
31
35
|
# @param events [Integer] bitwise-OR'd events you're interested in (see
|
@@ -34,11 +38,12 @@ module CZTop
|
|
34
38
|
# @raise [ArgumentError] if it's not a socket
|
35
39
|
def add(socket, events)
|
36
40
|
ptr = ptr_for_socket(socket)
|
37
|
-
rc
|
41
|
+
rc = ZMQ.poller_add(@poller_ptr, ptr, nil, events)
|
38
42
|
HasFFIDelegate.raise_zmq_err if rc == -1
|
39
43
|
remember_socket(socket, events)
|
40
44
|
end
|
41
45
|
|
46
|
+
|
42
47
|
# Convenience method to register a socket for readability. See {#add}.
|
43
48
|
# @param socket [Socket, Actor] the socket
|
44
49
|
# @return [void]
|
@@ -46,6 +51,7 @@ module CZTop
|
|
46
51
|
add(socket, ZMQ::POLLIN)
|
47
52
|
end
|
48
53
|
|
54
|
+
|
49
55
|
# Convenience method to register a socket for writability. See {#add}.
|
50
56
|
# @param socket [Socket, Actor] the socket
|
51
57
|
# @return [void]
|
@@ -53,6 +59,7 @@ module CZTop
|
|
53
59
|
add(socket, ZMQ::POLLOUT)
|
54
60
|
end
|
55
61
|
|
62
|
+
|
56
63
|
# Modifies the events of interest for the given socket.
|
57
64
|
# @param socket [Socket, Actor] the socket
|
58
65
|
# @param events [Integer] events you're interested in (see constants in
|
@@ -61,11 +68,12 @@ module CZTop
|
|
61
68
|
# @raise [ArgumentError] if it's not a socket
|
62
69
|
def modify(socket, events)
|
63
70
|
ptr = ptr_for_socket(socket)
|
64
|
-
rc
|
71
|
+
rc = ZMQ.poller_modify(@poller_ptr, ptr, events)
|
65
72
|
HasFFIDelegate.raise_zmq_err if rc == -1
|
66
73
|
remember_socket(socket, events)
|
67
74
|
end
|
68
75
|
|
76
|
+
|
69
77
|
# Removes a previously registered socket. Won't raise if you're
|
70
78
|
# trying to remove a socket that's not registered.
|
71
79
|
# @param socket [Socket, Actor] the socket
|
@@ -73,11 +81,12 @@ module CZTop
|
|
73
81
|
# @raise [ArgumentError] if it's not a socket
|
74
82
|
def remove(socket)
|
75
83
|
ptr = ptr_for_socket(socket)
|
76
|
-
rc
|
84
|
+
rc = ZMQ.poller_remove(@poller_ptr, ptr)
|
77
85
|
HasFFIDelegate.raise_zmq_err if rc == -1
|
78
86
|
forget_socket(socket)
|
79
87
|
end
|
80
88
|
|
89
|
+
|
81
90
|
# Removes a reader socket that was registered for readability only.
|
82
91
|
#
|
83
92
|
# @param socket [Socket, Actor] the socket
|
@@ -88,9 +97,10 @@ module CZTop
|
|
88
97
|
remove(socket)
|
89
98
|
return
|
90
99
|
end
|
91
|
-
raise ArgumentError,
|
100
|
+
raise ArgumentError, format('not registered for readability only: %p', socket)
|
92
101
|
end
|
93
102
|
|
103
|
+
|
94
104
|
# Removes a reader socket that was registered for writability only.
|
95
105
|
#
|
96
106
|
# @param socket [Socket, Actor] the socket
|
@@ -101,9 +111,10 @@ module CZTop
|
|
101
111
|
remove(socket)
|
102
112
|
return
|
103
113
|
end
|
104
|
-
raise ArgumentError,
|
114
|
+
raise ArgumentError, format('not registered for writability only: %p', socket)
|
105
115
|
end
|
106
116
|
|
117
|
+
|
107
118
|
# Waits for registered sockets to become readable or writable, depending
|
108
119
|
# on what you're interested in.
|
109
120
|
#
|
@@ -116,7 +127,7 @@ module CZTop
|
|
116
127
|
rc = ZMQ.poller_wait(@poller_ptr, @event_ptr, timeout)
|
117
128
|
if rc == -1
|
118
129
|
case CZMQ::FFI::Errors.errno
|
119
|
-
|
130
|
+
# NOTE: ETIMEDOUT for backwards compatibility, although this API is
|
120
131
|
# still DRAFT.
|
121
132
|
when Errno::EAGAIN::Errno, Errno::ETIMEDOUT::Errno
|
122
133
|
return nil
|
@@ -124,9 +135,10 @@ module CZTop
|
|
124
135
|
HasFFIDelegate.raise_zmq_err
|
125
136
|
end
|
126
137
|
end
|
127
|
-
|
138
|
+
Event.new(self, @event_ptr)
|
128
139
|
end
|
129
140
|
|
141
|
+
|
130
142
|
# Simpler version of {#wait}, which just returns the first socket of
|
131
143
|
# interest, if any. This is useful if you either have only reader sockets,
|
132
144
|
# or only have writer sockets.
|
@@ -140,27 +152,30 @@ module CZTop
|
|
140
152
|
return event.socket if event
|
141
153
|
end
|
142
154
|
|
155
|
+
|
143
156
|
# @param ptr [FFI::Pointer] pointer to the socket
|
144
157
|
# @return [Socket, Actor] socket corresponding to given pointer
|
145
158
|
# @raise [ArgumentError] if pointer is not known
|
146
159
|
def socket_for_ptr(ptr)
|
147
160
|
@sockets[ptr.to_i] or
|
148
|
-
raise ArgumentError,
|
161
|
+
raise ArgumentError, format('no socket known for pointer %p', ptr)
|
149
162
|
end
|
150
163
|
|
164
|
+
|
151
165
|
# @return [Array<CZTop::Socket>] all sockets registered with this poller
|
152
166
|
# @note The actual events registered for each sockets don't matter.
|
153
167
|
def sockets
|
154
168
|
@sockets.values
|
155
169
|
end
|
156
170
|
|
171
|
+
|
157
172
|
# Returns the event mask for the given, registered socket.
|
158
173
|
# @param socket [Socket, Actor] which socket's events to return
|
159
174
|
# @return [Integer] event mask for the given socket
|
160
175
|
# @raise [ArgumentError] if socket is not registered
|
161
176
|
def event_mask_for_socket(socket)
|
162
177
|
@events[socket] or
|
163
|
-
raise ArgumentError,
|
178
|
+
raise ArgumentError, format('no event mask known for socket %p', socket)
|
164
179
|
end
|
165
180
|
|
166
181
|
private
|
@@ -170,17 +185,20 @@ module CZTop
|
|
170
185
|
# @raise [ArgumentError] if argument is not a socket
|
171
186
|
def ptr_for_socket(socket)
|
172
187
|
raise ArgumentError unless socket.is_a?(Socket) || socket.is_a?(Actor)
|
188
|
+
|
173
189
|
Zsock.resolve(socket)
|
174
190
|
end
|
175
191
|
|
192
|
+
|
176
193
|
# Keeps a reference to the given socket, and remembers its event mask.
|
177
194
|
# @param socket [Socket, Actor] the socket
|
178
195
|
# @param events [Integer] the event mask
|
179
196
|
def remember_socket(socket, events)
|
180
197
|
@sockets[ptr_for_socket(socket).to_i] = socket
|
181
|
-
@events[socket]
|
198
|
+
@events[socket] = events
|
182
199
|
end
|
183
200
|
|
201
|
+
|
184
202
|
# Discards the referencel to the given socket, and forgets its event mask.
|
185
203
|
# @param socket [Socket, Actor] the socket
|
186
204
|
def forget_socket(socket)
|
@@ -188,33 +206,40 @@ module CZTop
|
|
188
206
|
@events.delete(socket)
|
189
207
|
end
|
190
208
|
|
209
|
+
|
191
210
|
# Represents an event returned by {CZTop::Poller#wait}. This is useful to
|
192
211
|
# find out whether the associated socket is now readable or writable, in
|
193
212
|
# case you're interested in both. For a simpler variant, check out
|
194
213
|
# {CZTop::Poller#simple_wait}.
|
195
214
|
class Event
|
215
|
+
|
196
216
|
# @param poller [CZTop::Poller] the poller instance
|
197
217
|
# @param event_ptr [FFI::Pointer] pointer to the memory allocated for
|
198
218
|
# the event's data (a +zmq_poller_event_t+)
|
199
219
|
def initialize(poller, event_ptr)
|
200
|
-
@poller
|
220
|
+
@poller = poller
|
201
221
|
@poller_event = ZMQ::PollerEvent.new(event_ptr)
|
202
222
|
end
|
203
223
|
|
224
|
+
|
204
225
|
# @return [Socket, Actor] the associated socket
|
205
226
|
def socket
|
206
227
|
@socket ||= @poller.socket_for_ptr(@poller_event[:socket])
|
207
228
|
end
|
208
229
|
|
230
|
+
|
209
231
|
# @return [Boolean] whether it's readable
|
210
232
|
def readable?
|
211
233
|
@poller_event.readable?
|
212
234
|
end
|
213
235
|
|
236
|
+
|
214
237
|
# @return [Boolean] whether it's writable
|
215
238
|
def writable?
|
216
239
|
@poller_event.writable?
|
217
240
|
end
|
241
|
+
|
218
242
|
end
|
243
|
+
|
219
244
|
end
|
220
245
|
end
|
@@ -1,24 +1,29 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module CZTop
|
3
4
|
# These are methods that can be used on a {Socket} as well as an {Actor}.
|
4
5
|
# @see http://api.zeromq.org/czmq3-0:zsock
|
5
6
|
module PolymorphicZsockMethods
|
7
|
+
|
6
8
|
# Sends a signal.
|
7
9
|
# @param status [Integer] signal (0-255)
|
8
10
|
def signal(status = 0)
|
9
11
|
::CZMQ::FFI::Zsock.signal(ffi_delegate, status)
|
10
12
|
end
|
11
13
|
|
14
|
+
|
12
15
|
# Waits for a signal.
|
13
16
|
# @return [Integer] the received signal
|
14
17
|
def wait
|
15
18
|
::CZMQ::FFI::Zsock.wait(ffi_delegate)
|
16
19
|
end
|
17
20
|
|
21
|
+
|
18
22
|
# Set socket to use unbounded pipes (HWM=0); use this in cases when you are
|
19
23
|
# totally certain the message volume can fit in memory.
|
20
24
|
def set_unbounded
|
21
25
|
::CZMQ::FFI::Zsock.set_unbounded(ffi_delegate)
|
22
26
|
end
|
27
|
+
|
23
28
|
end
|
24
29
|
end
|