xchan.rb 0.18.0 → 0.19.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/README.md +54 -5
- data/lib/xchan/bytes.rb +0 -7
- data/lib/xchan/counter.rb +0 -1
- data/lib/xchan/null_lock.rb +44 -0
- data/lib/xchan/tempfile.rb +2 -2
- data/lib/xchan/unix_socket.rb +20 -43
- data/lib/xchan/version.rb +1 -1
- data/lib/xchan.rb +14 -5
- data/share/xchan.rb/examples/read_operations/1_blocking_read.rb +1 -0
- data/share/xchan.rb/examples/read_operations/2_nonblocking_read.rb +1 -0
- data/share/xchan.rb/examples/serialization/1_serializers.rb +1 -1
- data/share/xchan.rb/examples/socket/{2_options.rb → 1_options.rb} +3 -0
- data/share/xchan.rb/examples/write_operations/1_blocking_write.rb +2 -1
- data/share/xchan.rb/examples/write_operations/2_nonblocking_write.rb +2 -1
- data/test/readme_test.rb +3 -3
- data/test/xchan_test.rb +1 -1
- data/xchan.rb.gemspec +9 -2
- metadata +22 -15
- data/.github/workflows/tests.yml +0 -26
- data/.gitignore +0 -8
- data/.projectile +0 -5
- data/.rubocop.yml +0 -34
- data/.yardopts +0 -4
- data/Gemfile +0 -4
- data/LICENSE +0 -15
- data/Rakefile.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a87a4e61f65ec4df37ecc2b09efd3d9abd4d39e57ac936db27e43ace4e99818d
|
4
|
+
data.tar.gz: 1ac4be7c20abcdee66a441088e1a7bf67b92b96f63b16b3401227bb978afa6de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc46a04ae48123fbf24371bd3438013cfcb070e353993811d10b4ea9d8b63628b577bed465d441fab1d964a0dab4ec9a2040e293c59272faa6c2081819788383
|
7
|
+
data.tar.gz: 267dd70488de1b49c345c49a87c5f28a7bdf0713c20fdeeba2efbef13e2d114960dc021e3b1ec77df90ad3c1189772e3075dff3ce0f2ebfac27b727acc4a56a8
|
data/README.md
CHANGED
@@ -19,6 +19,7 @@ serializers are available by default: `xchan(:marshal)`,
|
|
19
19
|
`xchan(:json)`, and `xchan(:yaml)`.
|
20
20
|
|
21
21
|
```ruby
|
22
|
+
#!/usr/bin/env ruby
|
22
23
|
require "xchan"
|
23
24
|
|
24
25
|
##
|
@@ -44,6 +45,7 @@ blocks. The example performs a read that blocks until
|
|
44
45
|
the parent process writes to the channel:
|
45
46
|
|
46
47
|
```ruby
|
48
|
+
#!/usr/bin/env ruby
|
47
49
|
require "xchan"
|
48
50
|
|
49
51
|
ch = xchan(:marshal)
|
@@ -71,6 +73,7 @@ the method raises `Chan::WaitReadable` when a read from
|
|
71
73
|
blocks:
|
72
74
|
|
73
75
|
```ruby
|
76
|
+
#!/usr/bin/env ruby
|
74
77
|
require "xchan"
|
75
78
|
|
76
79
|
def read(ch)
|
@@ -103,9 +106,10 @@ process, or when a write to
|
|
103
106
|
blocks. The example fills the send buffer:
|
104
107
|
|
105
108
|
```ruby
|
109
|
+
#!/usr/bin/env ruby
|
106
110
|
require "xchan"
|
107
111
|
|
108
|
-
ch = xchan(:marshal,
|
112
|
+
ch = xchan(:marshal, sock: Socket::SOCK_STREAM)
|
109
113
|
sndbuf = ch.w.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF)
|
110
114
|
while ch.bytes_sent <= sndbuf.int
|
111
115
|
ch.send(1)
|
@@ -123,6 +127,7 @@ a lock held by another process, and the method raises
|
|
123
127
|
blocks. The example frees space on the send buffer:
|
124
128
|
|
125
129
|
```ruby
|
130
|
+
#!/usr/bin/env ruby
|
126
131
|
require "xchan"
|
127
132
|
|
128
133
|
def send_nonblock(ch, buf)
|
@@ -136,7 +141,7 @@ rescue Chan::WaitLockable
|
|
136
141
|
retry
|
137
142
|
end
|
138
143
|
|
139
|
-
ch = xchan(:marshal,
|
144
|
+
ch = xchan(:marshal, sock: Socket::SOCK_STREAM)
|
140
145
|
sndbuf = ch.w.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF)
|
141
146
|
while ch.bytes_sent <= sndbuf.int
|
142
147
|
send_nonblock(ch, 1)
|
@@ -146,6 +151,49 @@ end
|
|
146
151
|
# Blocked - free send buffer
|
147
152
|
```
|
148
153
|
|
154
|
+
### Lock
|
155
|
+
|
156
|
+
#### File
|
157
|
+
|
158
|
+
The default lock for a channel is a file lock. The locking mechanism is
|
159
|
+
implemented with the
|
160
|
+
[lockf](https://man.freebsd.org/cgi/man.cgi?query=lockf&apropos=0&sektion=3&manpath=FreeBSD+14.2-RELEASE+and+Ports&arch=default&format=html)
|
161
|
+
function from the C standard library. Nothing special has to be done to
|
162
|
+
use it, and it allows a channel to be safely accessed across multiple
|
163
|
+
processes:
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
#!/usr/bin/env ruby
|
167
|
+
require "xchan"
|
168
|
+
|
169
|
+
ch = xchan(:marshal, lock: :file)
|
170
|
+
5.times.map do
|
171
|
+
fork do
|
172
|
+
ch.send(5)
|
173
|
+
end
|
174
|
+
end.each { Process.wait(_1) }
|
175
|
+
```
|
176
|
+
|
177
|
+
#### Null
|
178
|
+
|
179
|
+
The null lock is the same as using no lock at all. The null lock is
|
180
|
+
implemented as a collection of no-op operations. The null lock is
|
181
|
+
implemented in the
|
182
|
+
[Chan::NullLock](https://0x1eef.github,io/x/xchan.rb/Chan/NullLock.html)
|
183
|
+
class, and in certain situations, it can be useful and preferable
|
184
|
+
to using a file lock:
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
#!/usr/bin/env ruby
|
188
|
+
require "xchan"
|
189
|
+
|
190
|
+
ch = xchan(:marshal, lock: :null)
|
191
|
+
fork do
|
192
|
+
ch.send(5)
|
193
|
+
end
|
194
|
+
Process.wait
|
195
|
+
```
|
196
|
+
|
149
197
|
### Socket
|
150
198
|
|
151
199
|
#### Options
|
@@ -158,6 +206,7 @@ returns the socket used for read operations, and
|
|
158
206
|
returns the socket used for write operations:
|
159
207
|
|
160
208
|
```ruby
|
209
|
+
#!/usr/bin/env ruby
|
161
210
|
require "xchan"
|
162
211
|
ch = xchan(:marshal)
|
163
212
|
|
@@ -189,11 +238,11 @@ xchan.rb can be installed via rubygems.org:
|
|
189
238
|
|
190
239
|
## Sources
|
191
240
|
|
192
|
-
* [
|
193
|
-
* [
|
241
|
+
* [github.com/@0x1eef](https://github.com/0x1eef/xchan.rb#readme)
|
242
|
+
* [gitlab.com/@0x1eef](https://gitlab.com/0x1eef/xchan.rb#about)
|
194
243
|
|
195
244
|
## License
|
196
245
|
|
197
246
|
[BSD Zero Clause](https://choosealicense.com/licenses/0bsd/)
|
198
247
|
<br>
|
199
|
-
See [LICENSE](./LICENSE)
|
248
|
+
See [share/xchan.rb/LICENSE](./share/xchan.rb/LICENSE)
|
data/lib/xchan/bytes.rb
CHANGED
@@ -13,7 +13,6 @@ class Chan::Bytes
|
|
13
13
|
##
|
14
14
|
# @param [String] tmpdir
|
15
15
|
# Directory where temporary files are stored
|
16
|
-
#
|
17
16
|
# @return [Chan::Bytes]
|
18
17
|
def initialize(tmpdir)
|
19
18
|
@io = Chan.temporary_file(%w[bytes .json], tmpdir:)
|
@@ -23,10 +22,8 @@ class Chan::Bytes
|
|
23
22
|
|
24
23
|
##
|
25
24
|
# Adds a count to the start of the collection
|
26
|
-
#
|
27
25
|
# @param [Integer] len
|
28
26
|
# The bytesize of an object
|
29
|
-
#
|
30
27
|
# @return [void]
|
31
28
|
def unshift(len)
|
32
29
|
return 0 if len.nil? || len.zero?
|
@@ -38,10 +35,8 @@ class Chan::Bytes
|
|
38
35
|
|
39
36
|
##
|
40
37
|
# Adds a count to the end of the collection
|
41
|
-
#
|
42
38
|
# @param [Integer] len
|
43
39
|
# The bytesize of an object
|
44
|
-
#
|
45
40
|
# @return [void]
|
46
41
|
def push(len)
|
47
42
|
return 0 if len.nil? || len.zero?
|
@@ -53,7 +48,6 @@ class Chan::Bytes
|
|
53
48
|
|
54
49
|
##
|
55
50
|
# Removes a count from the start of the collection
|
56
|
-
#
|
57
51
|
# @return [Integer]
|
58
52
|
# Returns the removed byte count
|
59
53
|
def shift
|
@@ -73,7 +67,6 @@ class Chan::Bytes
|
|
73
67
|
|
74
68
|
##
|
75
69
|
# Close the underlying IO
|
76
|
-
#
|
77
70
|
# @return [void]
|
78
71
|
def close
|
79
72
|
@io.close
|
data/lib/xchan/counter.rb
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# {Chan::NullLock Chan::NullLock} is a no-op lock that can be used
|
5
|
+
# instead of the standard file lock when a lock is not needed
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# ch = xchan(:marshal, lock: Chan::NullLock)
|
9
|
+
# ch.send([1,2,3])
|
10
|
+
# # ditto
|
11
|
+
# ch = xchan(:marshal, lock: :null)
|
12
|
+
# ch.send([1,2,3])
|
13
|
+
class Chan::NullLock
|
14
|
+
##
|
15
|
+
# @return [void]
|
16
|
+
# This method is a no-op
|
17
|
+
def self.lock
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# @return [void]
|
22
|
+
# This method is a no-op
|
23
|
+
def self.lock_nonblock
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# @return [void]
|
28
|
+
# This method is a no-op
|
29
|
+
def self.release
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# @return [void]
|
34
|
+
# This method is a no-op
|
35
|
+
def self.close
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# @return [void]
|
40
|
+
# This method always returns false
|
41
|
+
def self.locked?
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
data/lib/xchan/tempfile.rb
CHANGED
data/lib/xchan/unix_socket.rb
CHANGED
@@ -29,24 +29,22 @@ class Chan::UNIXSocket
|
|
29
29
|
# ch.send([1,2,3])
|
30
30
|
# ch.recv.pop # => 3
|
31
31
|
# ch.close
|
32
|
-
#
|
33
|
-
# @param [Symbol, <#dump, #load>] s
|
32
|
+
# @param [Symbol, <#dump, #load>] serializer
|
34
33
|
# The name of a serializer
|
35
|
-
#
|
36
|
-
# @param [Integer] sock_type
|
34
|
+
# @param [Integer] sock
|
37
35
|
# Type of socket (eg `Socket::SOCK_STREAM`)
|
38
|
-
#
|
39
36
|
# @param [String] tmpdir
|
40
37
|
# Directory where temporary files can be stored
|
41
|
-
#
|
38
|
+
# @param [Symbol, <Lock::File, Chan::NullLock>] lock
|
39
|
+
# The name of a lock, or an instance of `Lock::File`, or {Chan::NullLock Chan::NullLock}
|
42
40
|
# @return [Chan::UNIXSocket]
|
43
41
|
# Returns an instance of {Chan::UNIXSocket Chan::UNIXSocket}
|
44
|
-
def initialize(
|
45
|
-
@s = Chan.serializers[
|
46
|
-
@r, @w = ::UNIXSocket.pair(
|
42
|
+
def initialize(serializer, sock: Socket::SOCK_DGRAM, tmpdir: Dir.tmpdir, lock: :file)
|
43
|
+
@s = Chan.serializers[serializer]&.call || serializer
|
44
|
+
@r, @w = ::UNIXSocket.pair(sock)
|
47
45
|
@bytes = Chan::Bytes.new(tmpdir)
|
48
46
|
@counter = Chan::Counter.new(tmpdir)
|
49
|
-
@
|
47
|
+
@lock = Chan.locks[lock]&.call(tmpdir) || lock
|
50
48
|
end
|
51
49
|
|
52
50
|
##
|
@@ -58,17 +56,15 @@ class Chan::UNIXSocket
|
|
58
56
|
|
59
57
|
##
|
60
58
|
# Closes the channel
|
61
|
-
#
|
62
59
|
# @raise [IOError]
|
63
60
|
# When the channel is closed
|
64
|
-
#
|
65
61
|
# @return [void]
|
66
62
|
def close
|
67
|
-
@
|
63
|
+
@lock.lock
|
68
64
|
raise IOError, "channel is closed" if closed?
|
69
|
-
[@r, @w, @bytes, @
|
65
|
+
[@r, @w, @bytes, @lock].each(&:close)
|
70
66
|
rescue IOError => ex
|
71
|
-
@
|
67
|
+
@lock.release
|
72
68
|
raise(ex)
|
73
69
|
end
|
74
70
|
|
@@ -77,13 +73,10 @@ class Chan::UNIXSocket
|
|
77
73
|
|
78
74
|
##
|
79
75
|
# Performs a blocking write
|
80
|
-
#
|
81
76
|
# @param [Object] object
|
82
77
|
# An object
|
83
|
-
#
|
84
78
|
# @raise [IOError]
|
85
79
|
# When the channel is closed
|
86
|
-
#
|
87
80
|
# @return [Object]
|
88
81
|
# Returns the number of bytes written to the channel
|
89
82
|
def send(object)
|
@@ -95,30 +88,25 @@ class Chan::UNIXSocket
|
|
95
88
|
|
96
89
|
##
|
97
90
|
# Performs a non-blocking write
|
98
|
-
#
|
99
91
|
# @param [Object] object
|
100
92
|
# An object
|
101
|
-
#
|
102
93
|
# @raise [IOError]
|
103
94
|
# When the channel is closed
|
104
|
-
#
|
105
95
|
# @raise [Chan::WaitWritable]
|
106
96
|
# When a write to {#w} blocks
|
107
|
-
#
|
108
97
|
# @raise [Chan::WaitLockable]
|
109
98
|
# When a write blocks because of a lock held by another process
|
110
|
-
#
|
111
99
|
# @return [Integer, nil]
|
112
100
|
# Returns the number of bytes written to the channel
|
113
101
|
def send_nonblock(object)
|
114
|
-
@
|
102
|
+
@lock.lock_nonblock
|
115
103
|
raise IOError, "channel closed" if closed?
|
116
104
|
len = @w.write_nonblock(serialize(object))
|
117
105
|
@bytes.push(len)
|
118
106
|
@counter.increment!(bytes_written: len)
|
119
|
-
len.tap { @
|
107
|
+
len.tap { @lock.release }
|
120
108
|
rescue IOError, IO::WaitWritable, Errno::ENOBUFS => ex
|
121
|
-
@
|
109
|
+
@lock.release
|
122
110
|
raise Chan::WaitWritable, ex.message
|
123
111
|
rescue Errno::EWOULDBLOCK => ex
|
124
112
|
raise Chan::WaitLockable, ex.message
|
@@ -133,10 +121,8 @@ class Chan::UNIXSocket
|
|
133
121
|
|
134
122
|
##
|
135
123
|
# Performs a blocking read
|
136
|
-
#
|
137
124
|
# @raise [IOError]
|
138
125
|
# When the channel is closed
|
139
|
-
#
|
140
126
|
# @return [Object]
|
141
127
|
# Returns an object from the channel
|
142
128
|
def recv
|
@@ -151,31 +137,27 @@ class Chan::UNIXSocket
|
|
151
137
|
|
152
138
|
##
|
153
139
|
# Performs a non-blocking read
|
154
|
-
#
|
155
140
|
# @raise [IOError]
|
156
141
|
# When the channel is closed
|
157
|
-
#
|
158
142
|
# @raise [Chan::WaitReadable]
|
159
143
|
# When a read from {#r} blocks
|
160
|
-
#
|
161
144
|
# @raise [Chan::WaitLockable]
|
162
145
|
# When a read blocks because of a lock held by another process
|
163
|
-
#
|
164
146
|
# @return [Object]
|
165
147
|
# Returns an object from the channel
|
166
148
|
def recv_nonblock
|
167
|
-
@
|
149
|
+
@lock.lock_nonblock
|
168
150
|
raise IOError, "closed channel" if closed?
|
169
151
|
len = @bytes.shift
|
170
152
|
obj = deserialize(@r.read_nonblock(len.zero? ? 1 : len))
|
171
153
|
@counter.increment!(bytes_read: len)
|
172
|
-
obj.tap { @
|
154
|
+
obj.tap { @lock.release }
|
173
155
|
rescue IOError => ex
|
174
|
-
@
|
156
|
+
@lock.release
|
175
157
|
raise(ex)
|
176
158
|
rescue IO::WaitReadable => ex
|
177
159
|
@bytes.unshift(len)
|
178
|
-
@
|
160
|
+
@lock.release
|
179
161
|
raise Chan::WaitReadable, ex.message
|
180
162
|
rescue Errno::EAGAIN => ex
|
181
163
|
raise Chan::WaitLockable, ex.message
|
@@ -190,7 +172,6 @@ class Chan::UNIXSocket
|
|
190
172
|
# ch = xchan(:pure)
|
191
173
|
# 1.upto(4) { ch.send(_1) }
|
192
174
|
# ch.to_a.last # => "4"
|
193
|
-
#
|
194
175
|
# @return [Array<Object>]
|
195
176
|
# Returns the contents of the channel
|
196
177
|
def to_a
|
@@ -241,10 +222,8 @@ class Chan::UNIXSocket
|
|
241
222
|
|
242
223
|
##
|
243
224
|
# Waits for the channel to become readable
|
244
|
-
#
|
245
225
|
# @param [Float, Integer, nil] s
|
246
226
|
# The number of seconds to wait. Waits indefinitely with no arguments.
|
247
|
-
#
|
248
227
|
# @return [Chan::UNIXSocket, nil]
|
249
228
|
# Returns self when the channel is readable, otherwise returns nil
|
250
229
|
def wait_readable(s = nil)
|
@@ -253,10 +232,8 @@ class Chan::UNIXSocket
|
|
253
232
|
|
254
233
|
##
|
255
234
|
# Waits for the channel to become writable
|
256
|
-
#
|
257
235
|
# @param [Float, Integer, nil] s
|
258
236
|
# The number of seconds to wait. Waits indefinitely with no arguments.
|
259
|
-
#
|
260
237
|
# @return [Chan::UNIXSocket, nil]
|
261
238
|
# Returns self when the channel is writable, otherwise returns nil
|
262
239
|
def wait_writable(s = nil)
|
@@ -269,10 +246,10 @@ class Chan::UNIXSocket
|
|
269
246
|
private
|
270
247
|
|
271
248
|
def lock
|
272
|
-
@
|
249
|
+
@lock.lock
|
273
250
|
yield
|
274
251
|
ensure
|
275
|
-
@
|
252
|
+
@lock.release
|
276
253
|
end
|
277
254
|
|
278
255
|
def serialize(obj)
|
data/lib/xchan/version.rb
CHANGED
data/lib/xchan.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
module Chan
|
4
4
|
require_relative "xchan/version"
|
5
5
|
require_relative "xchan/unix_socket"
|
6
|
+
require_relative "xchan/null_lock"
|
6
7
|
require_relative "xchan/tempfile"
|
7
8
|
|
8
9
|
WaitReadable = Class.new(IO::EAGAINWaitReadable)
|
@@ -32,10 +33,8 @@ module Chan
|
|
32
33
|
#
|
33
34
|
# @param [String] basename
|
34
35
|
# Basename of the temporary file
|
35
|
-
#
|
36
36
|
# @param [String] tmpdir
|
37
37
|
# Parent directory of the temporary file
|
38
|
-
#
|
39
38
|
# @return [Chan::Tempfile]
|
40
39
|
# Returns an instance of {Chan::Tempfile Chan::Tempfile}
|
41
40
|
def self.temporary_file(basename, tmpdir: Dir.tmpdir)
|
@@ -59,6 +58,16 @@ module Chan
|
|
59
58
|
}
|
60
59
|
}
|
61
60
|
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# @return [Hash<Symbol, Proc>]
|
64
|
+
# Returns the default locks
|
65
|
+
def self.locks
|
66
|
+
{
|
67
|
+
null: lambda { |_tmpdir| Chan::NullLock },
|
68
|
+
file: lambda { |tmpdir| Lock::File.new Chan.temporary_file(%w[xchan lock], tmpdir:) }
|
69
|
+
}
|
70
|
+
end
|
62
71
|
end
|
63
72
|
|
64
73
|
module Kernel
|
@@ -68,10 +77,10 @@ module Kernel
|
|
68
77
|
# ch.send([1,2,3])
|
69
78
|
# ch.recv.pop # => 3
|
70
79
|
# ch.close
|
71
|
-
#
|
72
|
-
# @param
|
73
|
-
# @param sock_type (see Chan::UNIXSocket#initialize)
|
80
|
+
# @param serializer (see Chan::UNIXSocket#initialize)
|
81
|
+
# @param sock (see Chan::UNIXSocket#initialize)
|
74
82
|
# @param tmpdir (see Chan::UNIXSocket#initialize)
|
83
|
+
# @param lock (see Chan::UNIXSocket#initialize)
|
75
84
|
# @return (see Chan::UNIXSocket#initialize)
|
76
85
|
def xchan(s, ...)
|
77
86
|
Chan::UNIXSocket.new(s, ...)
|
@@ -1,9 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require_relative "../setup"
|
4
5
|
require "xchan"
|
5
6
|
|
6
|
-
ch = xchan(:marshal,
|
7
|
+
ch = xchan(:marshal, sock: Socket::SOCK_STREAM)
|
7
8
|
sndbuf = ch.w.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF)
|
8
9
|
while ch.bytes_sent <= sndbuf.int
|
9
10
|
ch.send(1)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require_relative "../setup"
|
@@ -14,7 +15,7 @@ rescue Chan::WaitLockable
|
|
14
15
|
retry
|
15
16
|
end
|
16
17
|
|
17
|
-
ch = xchan(:marshal,
|
18
|
+
ch = xchan(:marshal, sock: Socket::SOCK_STREAM)
|
18
19
|
sndbuf = ch.w.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF)
|
19
20
|
while ch.bytes_sent <= sndbuf.int
|
20
21
|
send_nonblock(ch, 1)
|
data/test/readme_test.rb
CHANGED
@@ -27,10 +27,10 @@ class Chan::ReadmeTest < Test::Unit::TestCase
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_socket_2_options
|
30
|
-
r = 'The read buffer can contain a maximum of: \d{1,
|
31
|
-
'The maximum size of a single message is: \d{1,
|
30
|
+
r = 'The read buffer can contain a maximum of: \d{1,7} bytes.\s*' \
|
31
|
+
'The maximum size of a single message is: \d{1,7} bytes.\s*'
|
32
32
|
assert_match Regexp.new(r),
|
33
|
-
cmd("ruby", readme_example("socket/
|
33
|
+
cmd("ruby", readme_example("socket/1_options.rb"))
|
34
34
|
.stdout
|
35
35
|
.tr("\n", " ")
|
36
36
|
end
|
data/test/xchan_test.rb
CHANGED
data/xchan.rb.gemspec
CHANGED
@@ -8,15 +8,22 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.homepage = "https://github.com/0x1eef/xchan.rb#readme"
|
9
9
|
gem.version = Chan::VERSION
|
10
10
|
gem.licenses = ["0BSD"]
|
11
|
-
gem.files =
|
11
|
+
gem.files = Dir[
|
12
|
+
"README.md", "LICENSE",
|
13
|
+
"share/xchan.rb/**/*.rb",
|
14
|
+
"lib/*.rb", "lib/**/*.rb",
|
15
|
+
"test/*.rb", "test/**/*.rb",
|
16
|
+
"xchan.rb.gemspec"
|
17
|
+
]
|
12
18
|
gem.require_paths = ["lib"]
|
13
19
|
gem.summary = "An easy to use InterProcess Communication (IPC) library"
|
14
20
|
gem.description = gem.summary
|
15
21
|
gem.add_runtime_dependency "lockf.rb", "~> 2.1"
|
16
22
|
gem.add_development_dependency "test-unit", "~> 3.5.7"
|
17
23
|
gem.add_development_dependency "yard", "~> 0.9"
|
18
|
-
gem.add_development_dependency "
|
24
|
+
gem.add_development_dependency "kramdown", "~> 2.5"
|
19
25
|
gem.add_development_dependency "standard", "~> 1.13"
|
20
26
|
gem.add_development_dependency "test-cmd.rb", "~> 0.12.4"
|
21
27
|
gem.add_development_dependency "rake", "~> 13.1"
|
28
|
+
gem.add_development_dependency "irb", "~> 1.14"
|
22
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xchan.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- '0x1eef'
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lockf.rb
|
@@ -53,19 +53,19 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0.9'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: kramdown
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '2.5'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '2.5'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: standard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +108,20 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '13.1'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: irb
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.14'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.14'
|
111
125
|
description: An easy to use InterProcess Communication (IPC) library
|
112
126
|
email:
|
113
127
|
- 0x1eef@protonmail.com
|
@@ -115,18 +129,11 @@ executables: []
|
|
115
129
|
extensions: []
|
116
130
|
extra_rdoc_files: []
|
117
131
|
files:
|
118
|
-
- ".github/workflows/tests.yml"
|
119
|
-
- ".gitignore"
|
120
|
-
- ".projectile"
|
121
|
-
- ".rubocop.yml"
|
122
|
-
- ".yardopts"
|
123
|
-
- Gemfile
|
124
|
-
- LICENSE
|
125
132
|
- README.md
|
126
|
-
- Rakefile.rb
|
127
133
|
- lib/xchan.rb
|
128
134
|
- lib/xchan/bytes.rb
|
129
135
|
- lib/xchan/counter.rb
|
136
|
+
- lib/xchan/null_lock.rb
|
130
137
|
- lib/xchan/tempfile.rb
|
131
138
|
- lib/xchan/unix_socket.rb
|
132
139
|
- lib/xchan/version.rb
|
@@ -134,7 +141,7 @@ files:
|
|
134
141
|
- share/xchan.rb/examples/read_operations/2_nonblocking_read.rb
|
135
142
|
- share/xchan.rb/examples/serialization/1_serializers.rb
|
136
143
|
- share/xchan.rb/examples/setup.rb
|
137
|
-
- share/xchan.rb/examples/socket/
|
144
|
+
- share/xchan.rb/examples/socket/1_options.rb
|
138
145
|
- share/xchan.rb/examples/stress_tests/1_parallel_access_stress_test.rb
|
139
146
|
- share/xchan.rb/examples/write_operations/1_blocking_write.rb
|
140
147
|
- share/xchan.rb/examples/write_operations/2_nonblocking_write.rb
|
@@ -161,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
168
|
- !ruby/object:Gem::Version
|
162
169
|
version: '0'
|
163
170
|
requirements: []
|
164
|
-
rubygems_version: 3.5.
|
171
|
+
rubygems_version: 3.5.23
|
165
172
|
signing_key:
|
166
173
|
specification_version: 4
|
167
174
|
summary: An easy to use InterProcess Communication (IPC) library
|
data/.github/workflows/tests.yml
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
name: xchan.rb
|
2
|
-
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
branches: [ main ]
|
6
|
-
pull_request:
|
7
|
-
branches: [ main ]
|
8
|
-
|
9
|
-
jobs:
|
10
|
-
specs:
|
11
|
-
strategy:
|
12
|
-
fail-fast: false
|
13
|
-
matrix:
|
14
|
-
os: [ubuntu-latest, macos-latest]
|
15
|
-
ruby: [3.2, 3.3]
|
16
|
-
runs-on: ${{ matrix.os }}
|
17
|
-
steps:
|
18
|
-
- uses: actions/checkout@v2
|
19
|
-
- uses: ruby/setup-ruby@v1
|
20
|
-
with:
|
21
|
-
ruby-version: ${{ matrix.ruby }}
|
22
|
-
- run: bundle install
|
23
|
-
- run: SERIALIZER=marshal; for t in *_test.rb; do ruby test/${t}; done
|
24
|
-
- run: SERIALIZER=json; for t in *_test.rb; do ruby test/${t}; done
|
25
|
-
- run: SERIALIZER=yaml; for t in *_test.rb; do ruby test/${t}; done
|
26
|
-
- run: SERIALIZER=pure; for t in *_test.rb; do ruby test/${t}; done
|
data/.gitignore
DELETED
data/.projectile
DELETED
data/.rubocop.yml
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# Plugins
|
3
|
-
require:
|
4
|
-
- standard
|
5
|
-
|
6
|
-
##
|
7
|
-
# Defaults: standard-rb
|
8
|
-
inherit_gem:
|
9
|
-
standard: config/base.yml
|
10
|
-
|
11
|
-
##
|
12
|
-
# All cops
|
13
|
-
AllCops:
|
14
|
-
TargetRubyVersion: 3.2
|
15
|
-
Include:
|
16
|
-
- lib/*.rb
|
17
|
-
- lib/**/*.rb
|
18
|
-
- test/*_test.rb
|
19
|
-
|
20
|
-
##
|
21
|
-
# Enabled
|
22
|
-
Style/FrozenStringLiteralComment:
|
23
|
-
Enabled: true
|
24
|
-
|
25
|
-
##
|
26
|
-
# Disabled
|
27
|
-
Layout/ArgumentAlignment:
|
28
|
-
Enabled: false
|
29
|
-
Layout/MultilineMethodCallIndentation:
|
30
|
-
Enabled: false
|
31
|
-
Layout/EmptyLineBetweenDefs:
|
32
|
-
Enabled: false
|
33
|
-
Style/TrivialAccessors:
|
34
|
-
Enabled: false
|
data/.yardopts
DELETED
data/Gemfile
DELETED
data/LICENSE
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
Copyright (C) 2023 by 0x1eef <0x1eef@protonmail.com>
|
2
|
-
|
3
|
-
Permission to use, copy, modify, and/or distribute this
|
4
|
-
software for any purpose with or without fee is hereby
|
5
|
-
granted.
|
6
|
-
|
7
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
|
8
|
-
ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
9
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
10
|
-
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
11
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
12
|
-
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
13
|
-
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
14
|
-
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
15
|
-
OF THIS SOFTWARE.
|