xchan.rb 0.16.5 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5030f45f888a9c83fadde357be0c919cece744735af66016d80bcd5a9970dcc
4
- data.tar.gz: b9de8383ad5af12a57586087c0c95b37d08ff07e7838b12471583c06ebec214b
3
+ metadata.gz: 5509107cf1cda5e847f3c15e19c81ba9323c2dbb524a7ef808eeb820d5bcdeb9
4
+ data.tar.gz: 43deff543ee38ace3ca8a083a043eb1c6bbedec9143bd2c8e17de50f13127031
5
5
  SHA512:
6
- metadata.gz: 6716dcd591f6384a8665e2601fcc10d17f7ecb2842ed656ffc13de90d785bf5bd2e089fcc2ef5bba2a58ebde0b544014cc769cec6315413d0ac7c32d99724930
7
- data.tar.gz: 578c4aedba9104f7eeec52d1780df6ac7e7caed3040f19da4e4f20b436031e60f79ce2e7300e5ce6abbd6d638406143b5bcb0a4335b4400ae27cba05743f0db2
6
+ metadata.gz: d5455dd6c714bc4060ec1f563b46d8a9eaee32e5aa58c2a2508de99f53fc29e346d07ac04e719822bc394b66ac6ba6ddf5585bf7958c606a0f1f375c113b4310
7
+ data.tar.gz: '09bd28506d18a63e8e917ad1189c708cc6643b852707508ee0edf563064bd3618d3ae251d85e06f618672c414537b4da3db0538b61e4c11c2a6c64fff3394f38'
@@ -12,7 +12,7 @@ jobs:
12
12
  fail-fast: false
13
13
  matrix:
14
14
  os: [ubuntu-latest, macos-latest]
15
- ruby: [3.1, 3.2]
15
+ ruby: [3.1, 3.2, 3.3]
16
16
  runs-on: ${{ matrix.os }}
17
17
  steps:
18
18
  - uses: actions/checkout@v2
@@ -23,4 +23,4 @@ jobs:
23
23
  - run: SERIALIZER=marshal bundle exec rake
24
24
  - run: SERIALIZER=json bundle exec rake
25
25
  - run: SERIALIZER=yaml bundle exec rake
26
- - run: SERIALIZER=plain bundle exec rake
26
+ - run: SERIALIZER=pure bundle exec rake
data/.gitlab-ci.yml CHANGED
@@ -9,4 +9,4 @@ test-ruby32:
9
9
  - SERIALIZER=marshal bundle exec rake
10
10
  - SERIALIZER=json bundle exec rake
11
11
  - SERIALIZER=yaml bundle exec rake
12
- - SERIALIZER=plain bundle exec rake
12
+ - SERIALIZER=pure bundle exec rake
data/.projectile CHANGED
@@ -1 +1,4 @@
1
1
  +.
2
+ -/doc/
3
+ -/.yardoc/
4
+ -/.gems/
data/Gemfile CHANGED
@@ -1,6 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  source "https://rubygems.org"
4
- gem "lockf.rb", github: "0x1eef/lockf.rb", tag: "v0.10.6"
5
- gem "test-cmd.rb", github: "0x1eef/test-cmd.rb", tag: "v0.2.0"
6
4
  gemspec
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  ## About
2
2
 
3
- xchan.rb is an easy to use library that provides a channel for
4
- InterProcess Communication (IPC) between a parent Ruby process,
5
- and its child processes. The channel is implemented through both
6
- serialization, and an unbound unix socket.
3
+ xchan.rb is an easy to use library for InterProcess
4
+ Communication (IPC). The library provides a channel
5
+ that can transfer Ruby objects between Ruby processes
6
+ with a parent <-> child relationship.
7
7
 
8
8
  ## Examples
9
9
 
@@ -11,58 +11,53 @@ serialization, and an unbound unix socket.
11
11
 
12
12
  #### Options
13
13
 
14
- When a channel is written to or read from, a Ruby object is serialized
15
- (on write) or deserialized (on read). The default serializers are available as
16
- `xchan(:marshal)`, `xchan(:json)`, and `xchan(:yaml)`. For scenarios where it
17
- is preferred to send and receive plain strings, the "plain" serializer is
18
- available as `xchan(:plain)`. This example uses
14
+ The first argument given to xchan is the serializer
15
+ that it should use. A channel that will communicate
16
+ in pure strings (ie with no serialization) is
17
+ available as `xchan(:pure)`.
18
+
19
+ Otherwise, when a channel is written to or read from,
20
+ a Ruby object is serialized (on write) or deserialized
21
+ (on read). The serializers available to choose from
22
+ are `xchan(:marshal)`, `xchan(:json)`, and `xchan(:yaml)`.
23
+ The example uses
19
24
  [`Marshal`](https://www.rubydoc.info/stdlib/core/Marshal):
20
25
 
21
26
  ```ruby
22
27
  require "xchan"
23
28
 
24
29
  ##
25
- # This channel uses Marshal to serialize objects.
26
- ch = xchan
27
- pid = fork { print "Received message: ", ch.recv[:msg], "\n" }
28
- ch.send(msg: "serialized by Marshal")
29
- ch.close
30
- Process.wait(pid)
31
-
32
- ##
33
- # This channel also uses Marshal to serialize objects.
30
+ # This channel uses Marshal to serialize objects
34
31
  ch = xchan(:marshal)
35
- pid = fork { print "Received message: ", ch.recv[:msg], "\n"
36
- ch.send(msg: "serialized by Marshal")
32
+ Process.wait fork { ch.send(5) }
33
+ print "There are ", ch.recv + 7, " disciples and the same number of tribes", "\n"
37
34
  ch.close
38
- Process.wait(pid)
39
35
 
40
36
  ##
41
- # Received message: serialized by Marshal
42
- # Received message: serialized by Marshal
37
+ # There are 12 disciples and the same number of tribes
43
38
  ```
44
39
 
45
40
  ### Read operations
46
41
 
47
42
  #### `#recv`
48
43
 
49
- The `ch.recv` method performs a blocking read. A read can block when
50
- a lock is held by another process, or when a read from the underlying
51
- socket blocks. This example performs a read that blocks in a child
52
- process until the parent process writes to the channel:
44
+ The `ch.recv` method performs a blocking read. A read
45
+ can block when a lock is held by another process, or
46
+ when a read from
47
+ [Chan::UNIXSocket#r](https://0x1eef.github,io/x/xchan.rb/Chan/UNIXSocket.html#r-instance_method)
48
+ blocks. The example performs a read that blocks until
49
+ the parent process writes to the channel:
53
50
 
54
51
  ```ruby
55
52
  require "xchan"
56
53
 
57
- ch = xchan
58
- pid = fork do
54
+ ch = xchan(:marshal)
55
+ Process.detach fork {
59
56
  print "Received a random number (child process): ", ch.recv, "\n"
60
- end
61
- # Delay for a second to let a process fork, and call "ch.recv"
57
+ }
62
58
  sleep(1)
63
59
  print "Send a random number (from parent process)", "\n"
64
60
  ch.send(rand(21))
65
- Process.wait(pid)
66
61
  ch.close
67
62
 
68
63
  ##
@@ -72,11 +67,12 @@ ch.close
72
67
 
73
68
  #### `#recv_nonblock`
74
69
 
75
- The non-blocking counterpart to `#recv` is `#recv_nonblock`. The `#recv_nonblock`
76
- method raises `Chan::WaitLockable` when a read blocks because of a lock held by
77
- another process, and the method raises `Chan::WaitReadable` when a read on the
78
- underlying socket blocks. This example performs a read that will
79
- raise `Chan::WaitReadable`:
70
+ The non-blocking counterpart to `#recv` is `#recv_nonblock`.
71
+ The `#recv_nonblock` method raises `Chan::WaitLockable` when
72
+ a read blocks because of a lock held by another process, and
73
+ the method raises `Chan::WaitReadable` when a read from
74
+ [Chan::UNIXSocket#r](https://0x1eef.github,io/x/xchan.rb/Chan/UNIXSocket.html#r-instance_method)
75
+ blocks:
80
76
 
81
77
  ```ruby
82
78
  require "xchan"
@@ -92,7 +88,7 @@ rescue Chan::WaitLockable
92
88
  retry
93
89
  end
94
90
  trap("SIGINT") { exit(1) }
95
- read(xchan)
91
+ read(xchan(:marshal))
96
92
 
97
93
  ##
98
94
  # Wait 1 second for channel to be readable
@@ -104,15 +100,17 @@ read(xchan)
104
100
 
105
101
  #### `#send`
106
102
 
107
- The `ch.send` method performs a blocking write. A write can block when a lock
108
- is held by another process, or when a write to the underlying socket blocks.
109
- This example performs a write that will block when the send buffer becomes full:
103
+ The `ch.send` method performs a blocking write.
104
+ A write can block when a lock is held by another
105
+ process, or when a write to
106
+ [Chan::UNIXSocket#w](https://0x1eef.github,io/x/xchan.rb/Chan/UNIXSocket.html#w-instance_method)
107
+ blocks. The example fills the send buffer:
110
108
 
111
109
  ```ruby
112
110
  require "xchan"
113
111
 
114
112
  ch = xchan(:marshal, sock_type: Socket::SOCK_STREAM)
115
- sndbuf = ch.getsockopt(:reader, Socket::SOL_SOCKET, Socket::SO_SNDBUF)
113
+ sndbuf = ch.w.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF)
116
114
  while ch.bytes_sent <= sndbuf.int
117
115
  ch.send(1)
118
116
  end
@@ -120,11 +118,13 @@ end
120
118
 
121
119
  #### `#send_nonblock`
122
120
 
123
- The non-blocking counterpart to `#send` is `#send_nonblock`. The `#send_nonblock`
124
- method raises `Chan::WaitLockable` when a write blocks because of a lock held
125
- by another process, and the method raises `Chan::WaitReadable` when a write to
126
- the underlying socket blocks. This example builds on the previous example by
127
- freeing space on the send buffer when a write is found to block:
121
+ The non-blocking counterpart to `#send` is
122
+ `#send_nonblock`. The `#send_nonblock` method raises
123
+ `Chan::WaitLockable` when a write blocks because of
124
+ a lock held by another process, and the method raises
125
+ `Chan::WaitWritable` when a write to
126
+ [Chan::UNIXSocket#w](https://0x1eef.github,io/x/xchan.rb/Chan/UNIXSocket.html#w-instance_method)
127
+ blocks. The example frees space on the send buffer:
128
128
 
129
129
  ```ruby
130
130
  require "xchan"
@@ -141,7 +141,7 @@ rescue Chan::WaitLockable
141
141
  end
142
142
 
143
143
  ch = xchan(:marshal, sock_type: Socket::SOCK_STREAM)
144
- sndbuf = ch.getsockopt(:writer, Socket::SOL_SOCKET, Socket::SO_SNDBUF)
144
+ sndbuf = ch.w.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF)
145
145
  while ch.bytes_sent <= sndbuf.int
146
146
  send_nonblock(ch, 1)
147
147
  end
@@ -152,31 +152,14 @@ end
152
152
 
153
153
  ### Socket
154
154
 
155
- #### Types
156
-
157
- A channel can be created with one of three sockets types:
158
-
159
- * `Socket::SOCK_DGRAM`
160
- * `Socket::SOCK_STREAM`
161
- * `Socket::SOCK_SEQPACKET`
162
-
163
- The default is `Socket::SOCK_DGRAM` because its default settings
164
- provide the most buffer space. The socket type can be specified as
165
- a keyword argument:
166
-
167
- ```ruby
168
- require "xchan"
169
- ch = xchan(:marshal, sock_type: Socket::SOCK_STREAM)
170
- ```
171
-
172
155
  #### Options
173
156
 
174
- A channel is composed of two sockets, one for reading and the other for writing.
175
- Socket options can be read and set on either of the two sockets with the
176
- `Chan::UNIXSocket#getsockopt`, and `Chan::UNIXSocket#setsockopt` methods.
177
- Besides the first argument (`:reader`, or `:writer`), the rest of the arguments
178
- are identical to `Socket#{getsockopt,setsockopt}`. This example's results can
179
- vary depending on the operating system it is run on:
157
+ A channel has one socket for read operations and another
158
+ socket for write operations.
159
+ [Chan::UNIXSocket#r](https://0x1eef.github,io/x/xchan.rb/Chan/UNIXSocket.html#r-instance_method)
160
+ returns the socket used for read operations, and
161
+ [Chan::UNIXSocket#w](https://0x1eef.github,io/x/xchan.rb/Chan/UNIXSocket.html#w-instance_method)
162
+ returns the socket used for write operations:
180
163
 
181
164
  ```ruby
182
165
  require "xchan"
@@ -184,12 +167,12 @@ ch = xchan(:marshal)
184
167
 
185
168
  ##
186
169
  # Print the value of SO_RCVBUF
187
- rcvbuf = ch.getsockopt(:reader, Socket::SOL_SOCKET, Socket::SO_RCVBUF)
170
+ rcvbuf = ch.r.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVBUF)
188
171
  print "The read buffer can contain a maximum of: ", rcvbuf.int, " bytes.\n"
189
172
 
190
173
  ##
191
174
  # Print the value of SO_SNDBUF
192
- sndbuf = ch.getsockopt(:writer, Socket::SOL_SOCKET, Socket::SO_SNDBUF)
175
+ sndbuf = ch.w.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF)
193
176
  print "The maximum size of a single message is: ", sndbuf.int, " bytes.\n"
194
177
 
195
178
  ##
@@ -197,50 +180,22 @@ print "The maximum size of a single message is: ", sndbuf.int, " bytes.\n"
197
180
  # The maximum size of a single message is: 2048 bytes.
198
181
  ```
199
182
 
200
- ### Temporary files
183
+ ## Documentation
201
184
 
202
- #### tmpdir
185
+ A complete API reference is available at
186
+ [0x1eef.github.io/x/xchan.rb](https://0x1eef.github.io/x/xchan.rb/).
203
187
 
204
- A single channel creates three temporary files that are removed
205
- from the filesystem as soon as they are created. By default the
206
- files are stored - for a short time - in `Dir.tmpdir`. Read and
207
- write permissions are reserved for the process that created
208
- them, inclusive of its child processes.
188
+ ## Install
209
189
 
210
- The parent directory of the temporary files can be changed with the
211
- `tmpdir` option:
190
+ xchan.rb can be installed via rubygems.org:
212
191
 
213
- ```ruby
214
- require "xchan"
215
- ch = xchan(:marshal, tmpdir: Dir.home)
216
- ```
192
+ gem install xchan.rb
217
193
 
218
194
  ## Sources
219
195
 
220
196
  * [Source code (GitHub)](https://github.com/0x1eef/xchan.rb#readme)
221
197
  * [Source code (GitLab)](https://gitlab.com/0x1eef/xchan.rb#about)
222
198
 
223
- ## Install
224
-
225
- **Git**
226
-
227
- xchan.rb is distributed as a RubyGem through its git repositories. <br>
228
- [GitHub](https://github.com/0x1eef/xchan.rb),
229
- and
230
- [GitLab](https://gitlab.com/0x1eef/xchan.rb)
231
- are available as sources.
232
-
233
- ``` ruby
234
- # Gemfile
235
- gem "xchan.rb", github: "0x1eef/xchan.rb", tag: "v0.16.5"
236
- ```
237
-
238
- **Rubygems.org**
239
-
240
- xchan.rb can also be installed via rubygems.org.
241
-
242
- gem install xchan.rb
243
-
244
199
  ## <a id="license"> License </a>
245
200
 
246
201
  [BSD Zero Clause](https://choosealicense.com/licenses/0bsd/).
data/lib/xchan/bytes.rb CHANGED
@@ -1,39 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  ##
4
- # The {Chan::Bytes Chan::Bytes} class is similar
5
- # to an array, where each element represents the
6
- # number of bytes used to store an object on a
7
- # channel. When an object is written to a channel,
8
- # the array increases in size, and when an object
9
- # is read from a channel, the array decreases in
10
- # size.
4
+ # {Chan::Bytes Chan::Bytes} represents a collection
5
+ # of byte counts for each object stored on a channel.
6
+ # When an object is written to a channel, the collection
7
+ # increases in size, and when an object is read from
8
+ # a channel, the collection decreases in size.
11
9
  class Chan::Bytes
12
10
  require "json"
13
- require_relative "stat"
14
-
15
- ##
16
- # @return [Chan::Stat]
17
- attr_reader :stat
11
+ require_relative "counter"
18
12
 
19
13
  ##
20
14
  # @param [String] tmpdir
21
- # Path to a directory where temporary files will be stored.
15
+ # Directory where temporary files are stored
22
16
  #
23
17
  # @return [Chan::Bytes]
24
18
  def initialize(tmpdir)
25
- @serializer = JSON
26
19
  @io = Chan.temporary_file("xchan.bytes", tmpdir:)
27
20
  @io.sync = true
28
- @stat = Chan::Stat.new(tmpdir)
29
21
  write(@io, [])
30
22
  end
31
23
 
32
24
  ##
33
- # Insert a byte count at the head of the array
25
+ # Adds a count to the start of the collection
34
26
  #
35
27
  # @param [Integer] len
36
- # Number of bytes
28
+ # The bytesize of an object
37
29
  #
38
30
  # @return [void]
39
31
  def unshift(len)
@@ -41,15 +33,14 @@ class Chan::Bytes
41
33
  bytes = read(@io)
42
34
  bytes.unshift(len)
43
35
  write(@io, bytes)
44
- @stat.store(bytes_written: len)
45
36
  len
46
37
  end
47
38
 
48
39
  ##
49
- # Insert a byte count at the tail of the array
40
+ # Adds a count to the end of the collection
50
41
  #
51
42
  # @param [Integer] len
52
- # Number of bytes
43
+ # The bytesize of an object
53
44
  #
54
45
  # @return [void]
55
46
  def push(len)
@@ -57,25 +48,25 @@ class Chan::Bytes
57
48
  bytes = read(@io)
58
49
  bytes.push(len)
59
50
  write(@io, bytes)
60
- @stat.store(bytes_written: len)
61
51
  len
62
52
  end
63
53
 
64
54
  ##
55
+ # Removes a count from the start of the collection
56
+ #
65
57
  # @return [Integer]
66
- # Returns (and removes) a byte count from the head of the array
58
+ # Returns the removed byte count
67
59
  def shift
68
60
  bytes = read(@io)
69
61
  return 0 if bytes.size.zero?
70
62
  len = bytes.shift
71
63
  write(@io, bytes)
72
- @stat.store(bytes_read: len)
73
64
  len
74
65
  end
75
66
 
76
67
  ##
77
68
  # @return [Integer]
78
- # Returns the size of the array
69
+ # Returns the number of objects in the collection
79
70
  def size
80
71
  read(@io).size
81
72
  end
@@ -100,10 +91,10 @@ class Chan::Bytes
100
91
  end
101
92
 
102
93
  def serialize(bytes)
103
- @serializer.dump(bytes)
94
+ JSON.dump(bytes)
104
95
  end
105
96
 
106
97
  def deserialize(bytes)
107
- @serializer.load(bytes)
98
+ JSON.load(bytes)
108
99
  end
109
100
  end
@@ -1,33 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  ##
4
- # The {Chan::Stat Chan::Stat} class provides statistics
5
- # (eg number of bytes read, number of bytes written) for
6
- # a given channel.
7
- class Chan::Stat
4
+ # {Chan::Counter Chan::Counter} provides a counter
5
+ # for the number of written and received bytes on a
6
+ # given channel.
7
+ class Chan::Counter
8
8
  require "json"
9
9
 
10
10
  ##
11
11
  # @param [String] tmpdir
12
- # Path to a directory where temporary files will be stored.
12
+ # Directory where temporary files are stored
13
13
  #
14
- # @return [Chan::Stat]
14
+ # @return [Chan::Counter]
15
15
  def initialize(tmpdir)
16
- @serializer = JSON
17
- @io = Chan.temporary_file("xchan.stat", tmpdir:)
16
+ @io = Chan.temporary_file("xchan.counter", tmpdir:)
18
17
  write(@io, {"bytes_read" => 0, "bytes_written" => 0})
19
18
  end
20
19
 
21
20
  ##
22
21
  # @return [Integer]
23
- # Returns the number of bytes written to a channel.
22
+ # Returns the number of bytes written to a channel
24
23
  def bytes_written
25
24
  read(@io).fetch("bytes_written")
26
25
  end
27
26
 
28
27
  ##
29
28
  # @return [Integer]
30
- # Returns the number of bytes read from a channel.
29
+ # Returns the number of bytes read from a channel
31
30
  def bytes_read
32
31
  read(@io).fetch("bytes_read")
33
32
  end
@@ -36,7 +35,7 @@ class Chan::Stat
36
35
  # @param [Hash] new_stat
37
36
  # @return [void]
38
37
  # @private
39
- def store(new_stat)
38
+ def increment!(new_stat)
40
39
  stat = read(@io)
41
40
  new_stat.each { stat[_1.to_s] += _2 }
42
41
  write(@io, stat)
@@ -54,10 +53,10 @@ class Chan::Stat
54
53
  end
55
54
 
56
55
  def serialize(bytes)
57
- @serializer.dump(bytes)
56
+ JSON.dump(bytes)
58
57
  end
59
58
 
60
59
  def deserialize(bytes)
61
- @serializer.load(bytes)
60
+ JSON.load(bytes)
62
61
  end
63
62
  end
@@ -2,11 +2,7 @@ require 'delegate'
2
2
  require 'tmpdir'
3
3
 
4
4
  ##
5
- # {Chan::Tempfile Chan::Tempfile} is a fork of Tempfile from
6
- # Ruby's standard library. The primary difference between
7
- # {Chan::Tempfile Chan::Tempfile}, and the standard library is
8
- # that [ruby/tempfile#22](https://github.com/ruby/tempfile/pull/22)
9
- # is applied in this fork.
5
+ # @private
10
6
  class Chan::Tempfile < DelegateClass(File)
11
7
  VERSION = "0.1.3"
12
8
 
@@ -260,63 +256,63 @@ class Chan::Tempfile < DelegateClass(File)
260
256
  end
261
257
  end
262
258
 
263
- # Creates a file in the underlying file system;
264
- # returns a new \File object based on that file.
265
- #
266
- # With no block given and no arguments, creates and returns file whose:
267
- #
268
- # - Class is {File}[https://docs.ruby-lang.org/en/master/File.html] (not \Tempfile).
269
- # - Directory is the system temporary directory (system-dependent).
270
- # - Generated filename is unique in that directory.
271
- # - Permissions are <tt>0600</tt>;
272
- # see {File Permissions}[https://docs.ruby-lang.org/en/master/File.html#label-File+Permissions].
273
- # - Mode is <tt>'w+'</tt> (read/write mode, positioned at the end).
274
- #
275
- # With no block, the file is not removed automatically,
276
- # and so should be explicitly removed.
277
- #
278
- # Example:
279
- #
280
- # f = Tempfile.create # => #<File:/tmp/20220505-9795-17ky6f6>
281
- # f.class # => File
282
- # f.path # => "/tmp/20220505-9795-17ky6f6"
283
- # f.stat.mode.to_s(8) # => "100600"
284
- # File.exist?(f.path) # => true
285
- # File.unlink(f.path)
286
- # File.exist?(f.path) # => false
287
- #
288
- # Argument +basename+, if given, may be one of:
289
- #
290
- # - A string: the generated filename begins with +basename+:
291
- #
292
- # Tempfile.create('foo') # => #<File:/tmp/foo20220505-9795-1gok8l9>
293
- #
294
- # - An array of two strings <tt>[prefix, suffix]</tt>:
295
- # the generated filename begins with +prefix+ and ends with +suffix+:
296
- #
297
- # Tempfile.create(%w/foo .jpg/) # => #<File:/tmp/foo20220505-17839-tnjchh.jpg>
298
- #
299
- # With arguments +basename+ and +tmpdir+, the file is created in directory +tmpdir+:
300
- #
301
- # Tempfile.create('foo', '.') # => #<File:./foo20220505-9795-1emu6g8>
302
- #
303
- # Keyword arguments +mode+ and +options+ are passed directly to method
304
- # {File.open}[https://docs.ruby-lang.org/en/master/File.html#method-c-open]:
305
- #
306
- # - The value given with +mode+ must be an integer,
307
- # and may be expressed as the logical OR of constants defined in
308
- # {File::Constants}[https://docs.ruby-lang.org/en/master/File/Constants.html].
309
- # - For +options+, see {Open Options}[https://docs.ruby-lang.org/en/master/IO.html#class-IO-label-Open+Options].
310
- #
311
- # With a block given, creates the file as above, passes it to the block,
312
- # and returns the block's value;
313
- # before the return, the file object is closed and the underlying file is removed:
314
- #
315
- # Tempfile.create {|file| file.path } # => "/tmp/20220505-9795-rkists"
316
- #
317
- # Related: Tempfile.new.
318
- #
319
259
  module Chan
260
+ # Creates a file in the underlying file system;
261
+ # returns a new \File object based on that file.
262
+ #
263
+ # With no block given and no arguments, creates and returns file whose:
264
+ #
265
+ # - Class is {File}[https://docs.ruby-lang.org/en/master/File.html] (not \Tempfile).
266
+ # - Directory is the system temporary directory (system-dependent).
267
+ # - Generated filename is unique in that directory.
268
+ # - Permissions are <tt>0600</tt>;
269
+ # see {File Permissions}[https://docs.ruby-lang.org/en/master/File.html#label-File+Permissions].
270
+ # - Mode is <tt>'w+'</tt> (read/write mode, positioned at the end).
271
+ #
272
+ # With no block, the file is not removed automatically,
273
+ # and so should be explicitly removed.
274
+ #
275
+ # Example:
276
+ #
277
+ # f = Tempfile.create # => #<File:/tmp/20220505-9795-17ky6f6>
278
+ # f.class # => File
279
+ # f.path # => "/tmp/20220505-9795-17ky6f6"
280
+ # f.stat.mode.to_s(8) # => "100600"
281
+ # File.exist?(f.path) # => true
282
+ # File.unlink(f.path)
283
+ # File.exist?(f.path) # => false
284
+ #
285
+ # Argument +basename+, if given, may be one of:
286
+ #
287
+ # - A string: the generated filename begins with +basename+:
288
+ #
289
+ # Tempfile.create('foo') # => #<File:/tmp/foo20220505-9795-1gok8l9>
290
+ #
291
+ # - An array of two strings <tt>[prefix, suffix]</tt>:
292
+ # the generated filename begins with +prefix+ and ends with +suffix+:
293
+ #
294
+ # Tempfile.create(%w/foo .jpg/) # => #<File:/tmp/foo20220505-17839-tnjchh.jpg>
295
+ #
296
+ # With arguments +basename+ and +tmpdir+, the file is created in directory +tmpdir+:
297
+ #
298
+ # Tempfile.create('foo', '.') # => #<File:./foo20220505-9795-1emu6g8>
299
+ #
300
+ # Keyword arguments +mode+ and +options+ are passed directly to method
301
+ # {File.open}[https://docs.ruby-lang.org/en/master/File.html#method-c-open]:
302
+ #
303
+ # - The value given with +mode+ must be an integer,
304
+ # and may be expressed as the logical OR of constants defined in
305
+ # {File::Constants}[https://docs.ruby-lang.org/en/master/File/Constants.html].
306
+ # - For +options+, see {Open Options}[https://docs.ruby-lang.org/en/master/IO.html#class-IO-label-Open+Options].
307
+ #
308
+ # With a block given, creates the file as above, passes it to the block,
309
+ # and returns the block's value;
310
+ # before the return, the file object is closed and the underlying file is removed:
311
+ #
312
+ # Tempfile.create {|file| file.path } # => "/tmp/20220505-9795-rkists"
313
+ #
314
+ # Related: Tempfile.new.
315
+ #
320
316
  def Tempfile.create(basename="", tmpdir=nil, mode: 0, perm: 0600, **options)
321
317
  tmpfile = nil
322
318
  Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
@@ -1,13 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  ##
4
- # The {Chan::UNIXSocket Chan::UNIXSocket} class implements a channel
5
- # for interprocess communication (IPC) using an unnamed UNIXSocket.
4
+ # An easy-to-use InterProcess Communication (IPC) library.
6
5
  class Chan::UNIXSocket
7
6
  require "socket"
8
7
  require "lockf"
9
8
  require_relative "bytes"
10
9
 
10
+ ##
11
+ # @return [UNIXSocket]
12
+ # Returns a socket used for read operations
13
+ attr_reader :r
14
+
15
+ ##
16
+ # @return [UNIXSocket]
17
+ # Returns a socket used for write operations
18
+ attr_reader :w
19
+
11
20
  ##
12
21
  # @example
13
22
  # ch = Chan::UNIXSocket.new(:marshal)
@@ -16,39 +25,40 @@ class Chan::UNIXSocket
16
25
  # ch.close
17
26
  #
18
27
  # @param [Symbol, <#dump, #load>] serializer
19
- # A serializer.
28
+ # The name of a serializer
20
29
  #
21
30
  # @param [Integer] sock_type
22
- # A socket type (eg Socket::SOCK_STREAM).
31
+ # Type of socket (eg `Socket::SOCK_STREAM`)
23
32
  #
24
33
  # @param [String] tmpdir
25
- # Path to a directory where temporary files will be stored.
34
+ # Directory where temporary files can be stored
26
35
  #
27
36
  # @return [Chan::UNIXSocket]
28
- # Returns an instance of {Chan::UNIXSocket Chan::UNIXSocket}.
29
- def initialize(serializer, tmpdir: Dir.tmpdir, sock_type: Socket::SOCK_DGRAM)
37
+ # Returns an instance of {Chan::UNIXSocket Chan::UNIXSocket}
38
+ def initialize(serializer, sock_type: Socket::SOCK_DGRAM, tmpdir: Dir.tmpdir)
30
39
  @serializer = Chan.serializers[serializer]&.call || serializer
31
40
  @r, @w = ::UNIXSocket.pair(sock_type)
32
41
  @bytes = Chan::Bytes.new(tmpdir)
42
+ @counter = Chan::Counter.new(tmpdir)
33
43
  @lock = LockFile.new Chan.temporary_file("xchan.lock", tmpdir:)
34
44
  end
35
45
 
36
46
  ##
37
47
  # @return [<#dump, #load>]
38
- # Returns the serializer used by the channel.
48
+ # Returns the serializer used by the channel
39
49
  def serializer
40
50
  @serializer
41
51
  end
42
52
 
43
53
  ##
44
54
  # @return [Boolean]
45
- # Returns true when the channel is closed.
55
+ # Returns true when the channel is closed
46
56
  def closed?
47
57
  @r.closed? and @w.closed?
48
58
  end
49
59
 
50
60
  ##
51
- # Closes the channel.
61
+ # Closes the channel
52
62
  #
53
63
  # @raise [IOError]
54
64
  # When the channel is closed.
@@ -70,13 +80,13 @@ class Chan::UNIXSocket
70
80
  # Performs a blocking write
71
81
  #
72
82
  # @param [Object] object
73
- # An object to write to the channel.
83
+ # An object
74
84
  #
75
85
  # @raise [IOError]
76
- # When the channel is closed.
86
+ # When the channel is closed
77
87
  #
78
88
  # @return [Object]
79
- # Returns the number of bytes written to the channel.
89
+ # Returns the number of bytes written to the channel
80
90
  def send(object)
81
91
  send_nonblock(object)
82
92
  rescue Chan::WaitWritable, Chan::WaitLockable
@@ -88,24 +98,25 @@ class Chan::UNIXSocket
88
98
  # Performs a non-blocking write
89
99
  #
90
100
  # @param [Object] object
91
- # An object to write to the channel.
101
+ # An object
92
102
  #
93
103
  # @raise [IOError]
94
- # When the channel is closed.
104
+ # When the channel is closed
95
105
  #
96
106
  # @raise [Chan::WaitWritable]
97
- # When a write to the underlying IO blocks.
107
+ # When a write to {#w} blocks
98
108
  #
99
109
  # @raise [Chan::WaitLockable]
100
- # When a write blocks because of a lock held by another process.
110
+ # When a write blocks because of a lock held by another process
101
111
  #
102
112
  # @return [Integer, nil]
103
- # Returns the number of bytes written to the channel.
113
+ # Returns the number of bytes written to the channel
104
114
  def send_nonblock(object)
105
115
  @lock.lock_nonblock
106
116
  raise IOError, "channel closed" if closed?
107
117
  len = @w.write_nonblock(serialize(object))
108
118
  @bytes.push(len)
119
+ @counter.increment!(bytes_written: len)
109
120
  len.tap { @lock.release }
110
121
  rescue IOError, IO::WaitWritable, Errno::ENOBUFS => ex
111
122
  @lock.release
@@ -125,10 +136,10 @@ class Chan::UNIXSocket
125
136
  # Performs a blocking read
126
137
  #
127
138
  # @raise [IOError]
128
- # When the channel is closed.
139
+ # When the channel is closed
129
140
  #
130
141
  # @return [Object]
131
- # Returns an object from the channel.
142
+ # Returns an object from the channel
132
143
  def recv
133
144
  recv_nonblock
134
145
  rescue Chan::WaitReadable
@@ -143,21 +154,22 @@ class Chan::UNIXSocket
143
154
  # Performs a non-blocking read
144
155
  #
145
156
  # @raise [IOError]
146
- # When the channel is closed.
157
+ # When the channel is closed
147
158
  #
148
159
  # @raise [Chan::WaitReadable]
149
- # When a read from the underlying IO blocks.
160
+ # When a read from {#r} blocks
150
161
  #
151
162
  # @raise [Chan::WaitLockable]
152
- # When a read blocks because of a lock held by another process.
163
+ # When a read blocks because of a lock held by another process
153
164
  #
154
165
  # @return [Object]
155
- # Returns an object from the channel.
166
+ # Returns an object from the channel
156
167
  def recv_nonblock
157
168
  @lock.lock_nonblock
158
169
  raise IOError, "closed channel" if closed?
159
170
  len = @bytes.shift
160
171
  obj = deserialize(@r.read_nonblock(len.zero? ? 1 : len))
172
+ @counter.increment!(bytes_read: len)
161
173
  obj.tap { @lock.release }
162
174
  rescue IOError => ex
163
175
  @lock.release
@@ -181,7 +193,7 @@ class Chan::UNIXSocket
181
193
  # ch.to_a.last # => 4
182
194
  #
183
195
  # @return [Array<Object>]
184
- # Returns the consumed contents of the channel.
196
+ # Returns the contents of the channel
185
197
  def to_a
186
198
  lock do
187
199
  [].tap { _1.push(recv) until empty? }
@@ -190,28 +202,28 @@ class Chan::UNIXSocket
190
202
 
191
203
  ##
192
204
  # @return [Boolean]
193
- # Returns true when the channel is empty.
205
+ # Returns true when the channel is empty
194
206
  def empty?
195
207
  return true if closed?
196
208
  lock { size.zero? }
197
209
  end
198
210
 
199
211
  ##
200
- # @group Size methods
212
+ # @group Stat methods
201
213
 
202
214
  ##
203
215
  # @return [Integer]
204
- # Returns the total number of bytes written to the channel.
216
+ # Returns the total number of bytes written to the channel
205
217
  def bytes_sent
206
- lock { @bytes.stat.bytes_written }
218
+ lock { @counter.bytes_written }
207
219
  end
208
220
  alias_method :bytes_written, :bytes_sent
209
221
 
210
222
  ##
211
223
  # @return [Integer]
212
- # Returns the total number of bytes read from the channel.
224
+ # Returns the total number of bytes read from the channel
213
225
  def bytes_received
214
- lock { @bytes.stat.bytes_read }
226
+ lock { @counter.bytes_read }
215
227
  end
216
228
  alias_method :bytes_read, :bytes_received
217
229
 
@@ -255,61 +267,6 @@ class Chan::UNIXSocket
255
267
  ##
256
268
  # @endgroup
257
269
 
258
- ##
259
- # @group Socket options
260
-
261
- ##
262
- # @param [String, Symbol] target
263
- # `:reader`, or `:writer`.
264
- #
265
- # @param [Integer] level
266
- # The level (eg `Socket::SOL_SOCKET` for the socket level).
267
- #
268
- # @param [Integer] option_name
269
- # The name of an option (eg `Socket::SO_RCVBUF`).
270
- #
271
- # @param [Boolean, Integer] option_value
272
- # The option value (eg 12345)
273
- #
274
- # @return [Integer]
275
- # Returns 0 on success.
276
- def setsockopt(target, level, option_name, option_value)
277
- @lock.lock
278
- if !%w[reader writer].include?(target.to_s)
279
- raise ArgumentError, "target can be ':reader', or ':writer'"
280
- end
281
- target = (target == :reader) ? @r : @w
282
- target.setsockopt(level, option_name, option_value)
283
- ensure
284
- @lock.release
285
- end
286
-
287
- ##
288
- # @param [String, Symbol] target
289
- # `:reader`, or `:writer`.
290
- #
291
- # @param [Integer] level
292
- # The level (eg `Socket::SOL_SOCKET` for the socket level).
293
- #
294
- # @param [Integer] option_name
295
- # The name of an option (eg `Socket::SO_RCVBUF`).
296
- #
297
- # @return [Socket::Option]
298
- # Returns an instance of `Socket::Option`.
299
- def getsockopt(target, level, option_name)
300
- @lock.lock
301
- if !%w[reader writer].include?(target.to_s)
302
- raise ArgumentError, "target can be ':reader', or ':writer'"
303
- end
304
- target = (target == :reader) ? @r : @w
305
- target.getsockopt(level, option_name)
306
- ensure
307
- @lock.release
308
- end
309
-
310
- ##
311
- # @endgroup
312
-
313
270
  private
314
271
 
315
272
  def lock
data/lib/xchan/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Chan
4
- VERSION = "0.16.5"
4
+ VERSION = "0.17.1"
5
5
  end
data/lib/xchan.rb CHANGED
@@ -4,12 +4,25 @@ module Chan
4
4
  require_relative "xchan/version"
5
5
  require_relative "xchan/unix_socket"
6
6
  require_relative "xchan/tempfile"
7
- require_relative "xchan/mixin"
8
7
 
9
8
  WaitReadable = Class.new(IO::EAGAINWaitReadable)
10
9
  WaitWritable = Class.new(IO::EAGAINWaitWritable)
11
10
  WaitLockable = Class.new(Errno::EWOULDBLOCK)
12
- Plain = Class.new do
11
+
12
+ ##
13
+ # The Pure serializer won't perform
14
+ # serialization that goes beyond calling
15
+ # `.to_s` on the object it is given. It
16
+ # can be useful when you want to communicate
17
+ # purely in strings.
18
+ #
19
+ # @example
20
+ # ch = xchan(:pure)
21
+ # Process.wait fork {
22
+ # ch.send "Hello world"
23
+ # }
24
+ # puts ch.recv
25
+ Pure = Class.new do
13
26
  def self.dump(str) = str.to_s
14
27
  def self.load(str) = str.to_s
15
28
  end
@@ -21,20 +34,23 @@ module Chan
21
34
  # processes other than that.
22
35
  #
23
36
  # @param [String] basename
24
- # Basename of the temporary file.
37
+ # Basename of the temporary file
25
38
  #
26
39
  # @param [String] tmpdir
27
- # Parent directory of the temporary file.
40
+ # Parent directory of the temporary file
28
41
  #
29
42
  # @return [Chan::Tempfile]
30
- # Returns an instance of {Chan::Tempfile Chan::Tempfile}.
43
+ # Returns an instance of {Chan::Tempfile Chan::Tempfile}
31
44
  def self.temporary_file(basename, tmpdir: Dir.tmpdir)
32
45
  Chan::Tempfile.new(basename, tmpdir, perm: 0).tap(&:unlink)
33
46
  end
34
47
 
48
+ ##
49
+ # @return [Hash<Symbol, Proc>]
50
+ # A mapping of serializers
35
51
  def self.serializers
36
52
  {
37
- plain: lambda { Plain },
53
+ pure: lambda { Pure },
38
54
  marshal: lambda { Marshal },
39
55
  json: lambda {
40
56
  require "json" unless defined?(JSON)
@@ -48,6 +64,19 @@ module Chan
48
64
  end
49
65
  end
50
66
 
51
- class Object
52
- include Chan::Mixin
67
+ module Kernel
68
+ ##
69
+ # @example
70
+ # ch = xchan
71
+ # ch.send([1,2,3])
72
+ # ch.recv.pop # => 3
73
+ # ch.close
74
+ #
75
+ # @param serializer (see Chan::UNIXSocket#initialize)
76
+ # @param sock_type (see Chan::UNIXSocket#initialize)
77
+ # @param tmpdir (see Chan::UNIXSocket#initialize)
78
+ # @return (see Chan::UNIXSocket#initialize)
79
+ def xchan(serializer, **kw_args)
80
+ Chan::UNIXSocket.new(serializer, **kw_args)
81
+ end
53
82
  end
@@ -4,15 +4,13 @@ require_relative "../setup"
4
4
  require "xchan"
5
5
 
6
6
  $stdout.sync = true
7
- ch = xchan
8
- pid = fork do
7
+ ch = xchan(:marshal)
8
+ Process.detach fork {
9
9
  print "Received random number (child process): ", ch.recv, "\n"
10
- end
11
- # Delay for a second to let a process fork, and call "ch.recv"
10
+ }
12
11
  sleep(1)
13
12
  print "Send a random number (from parent process)", "\n"
14
13
  ch.send(rand(21))
15
- Process.wait(pid)
16
14
  ch.close
17
15
 
18
16
  ##
@@ -14,4 +14,4 @@ rescue Chan::WaitLockable
14
14
  retry
15
15
  end
16
16
  trap("SIGINT") { exit(1) }
17
- read(xchan)
17
+ read(xchan(:marshal))
@@ -4,17 +4,11 @@ require_relative "../setup"
4
4
  require "xchan"
5
5
 
6
6
  ##
7
- # This channel uses Marshal to serialize objects.
8
- ch = xchan
9
- pid = fork { print "Received message: ", ch.recv[:msg], "\n" }
10
- ch.send(msg: "serialized by Marshal")
7
+ # This channel uses Marshal to serialize objects
8
+ ch = xchan(:marshal)
9
+ Process.wait fork { ch.send(5) }
10
+ print "There are ", ch.recv + 7, " disciples and the same number of tribes", "\n"
11
11
  ch.close
12
- Process.wait(pid)
13
12
 
14
13
  ##
15
- # This channel also uses Marshal to serialize objects.
16
- ch = xchan(:marshal)
17
- pid = fork { print "Received message: ", ch.recv[:msg], "\n" }
18
- ch.send(msg: "serialized by Marshal")
19
- ch.close
20
- Process.wait(pid)
14
+ # There are 12 disciples and the same number of tribes
@@ -3,10 +3,10 @@ ch = xchan(:marshal)
3
3
 
4
4
  ##
5
5
  # Print the value of SO_RCVBUF
6
- rcvbuf = ch.getsockopt(:reader, Socket::SOL_SOCKET, Socket::SO_RCVBUF)
6
+ rcvbuf = ch.r.getsockopt(Socket::SOL_SOCKET, Socket::SO_RCVBUF)
7
7
  print "The read buffer can contain a maximum of: ", rcvbuf.int, " bytes.\n"
8
8
 
9
9
  ##
10
10
  # Print the value of SO_SNDBUF
11
- sndbuf = ch.getsockopt(:writer, Socket::SOL_SOCKET, Socket::SO_SNDBUF)
11
+ sndbuf = ch.w.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF)
12
12
  print "The maximum size of a single message is: ", sndbuf.int, " bytes.\n"
@@ -4,7 +4,7 @@ require_relative "../setup"
4
4
  require "xchan"
5
5
 
6
6
  ch = xchan(:marshal, sock_type: Socket::SOCK_STREAM)
7
- sndbuf = ch.getsockopt(:reader, Socket::SOL_SOCKET, Socket::SO_SNDBUF)
7
+ sndbuf = ch.w.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF)
8
8
  while ch.bytes_sent <= sndbuf.int
9
9
  ch.send(1)
10
10
  end
@@ -15,7 +15,7 @@ rescue Chan::WaitLockable
15
15
  end
16
16
 
17
17
  ch = xchan(:marshal, sock_type: Socket::SOCK_STREAM)
18
- sndbuf = ch.getsockopt(:writer, Socket::SOL_SOCKET, Socket::SO_SNDBUF)
18
+ sndbuf = ch.w.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF)
19
19
  while ch.bytes_sent <= sndbuf.int
20
20
  send_nonblock(ch, 1)
21
21
  end
data/test/readme_test.rb CHANGED
@@ -4,10 +4,8 @@ require_relative "setup"
4
4
  require "test/cmd"
5
5
 
6
6
  class Chan::ReadmeTest < Test::Unit::TestCase
7
- include Test::Cmd
8
-
9
7
  def test_serialization_1_serializers
10
- assert_equal "Received message: serialized by Marshal\n" * 2,
8
+ assert_equal "There are 12 disciples and the same number of tribes\n",
11
9
  readme_example("serialization/1_serializers.rb").stdout
12
10
  end
13
11
 
data/test/xchan_test.rb CHANGED
@@ -4,7 +4,7 @@ require_relative "setup"
4
4
 
5
5
  class Chan::Test < Test::Unit::TestCase
6
6
  def setup
7
- @ch = xchan ENV.fetch("SERIALIZER", "marshal").to_sym
7
+ @ch = xchan(serializer)
8
8
  end
9
9
 
10
10
  def teardown
@@ -17,9 +17,13 @@ class Chan::Test < Test::Unit::TestCase
17
17
  @ch
18
18
  end
19
19
 
20
+ def serializer
21
+ ENV.fetch("SERIALIZER", "pure").to_sym
22
+ end
23
+
20
24
  def object
21
- case ENV["SERIALIZER"]
22
- when "plain" then "xchan"
25
+ case serializer
26
+ when :pure then "xchan"
23
27
  else %w[xchan]
24
28
  end
25
29
  end
data/xchan.rb.gemspec CHANGED
@@ -10,13 +10,13 @@ Gem::Specification.new do |gem|
10
10
  gem.licenses = ["0BSD"]
11
11
  gem.files = `git ls-files`.split($/)
12
12
  gem.require_paths = ["lib"]
13
- gem.summary = "An easy to use InterProcess Communication (IPC) library."
13
+ gem.summary = "An easy to use InterProcess Communication (IPC) library"
14
14
  gem.description = gem.summary
15
- gem.add_runtime_dependency "lockf.rb", "~> 0.10.6"
15
+ gem.add_runtime_dependency "lockf.rb", "~> 1.0"
16
16
  gem.add_development_dependency "test-unit", "~> 3.5.7"
17
17
  gem.add_development_dependency "yard", "~> 0.9"
18
18
  gem.add_development_dependency "redcarpet", "~> 3.5"
19
19
  gem.add_development_dependency "standard", "~> 1.13"
20
- gem.add_development_dependency "test-cmd.rb", "~> 0.2"
20
+ gem.add_development_dependency "test-cmd.rb", "~> 0.8"
21
21
  gem.add_development_dependency "rake", "~> 13.1"
22
22
  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.16.5
4
+ version: 0.17.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - '0x1eef'
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-06 00:00:00.000000000 Z
11
+ date: 2024-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lockf.rb
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.10.6
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.10.6
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: test-unit
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.2'
89
+ version: '0.8'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0.2'
96
+ version: '0.8'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -108,7 +108,7 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '13.1'
111
- description: An easy to use InterProcess Communication (IPC) library.
111
+ description: An easy to use InterProcess Communication (IPC) library
112
112
  email:
113
113
  - 0x1eef@protonmail.com
114
114
  executables: []
@@ -127,8 +127,7 @@ files:
127
127
  - Rakefile.rb
128
128
  - lib/xchan.rb
129
129
  - lib/xchan/bytes.rb
130
- - lib/xchan/mixin.rb
131
- - lib/xchan/stat.rb
130
+ - lib/xchan/counter.rb
132
131
  - lib/xchan/tempfile.rb
133
132
  - lib/xchan/unix_socket.rb
134
133
  - lib/xchan/version.rb
@@ -163,8 +162,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
163
162
  - !ruby/object:Gem::Version
164
163
  version: '0'
165
164
  requirements: []
166
- rubygems_version: 3.5.3
165
+ rubygems_version: 3.5.9
167
166
  signing_key:
168
167
  specification_version: 4
169
- summary: An easy to use InterProcess Communication (IPC) library.
168
+ summary: An easy to use InterProcess Communication (IPC) library
170
169
  test_files: []
data/lib/xchan/mixin.rb DELETED
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ##
4
- # A module that is included into Ruby's {Object} class.
5
- module Chan::Mixin
6
- ##
7
- # @example
8
- # ch = xchan
9
- # ch.send([1,2,3])
10
- # ch.recv.pop # => 3
11
- # ch.close
12
- #
13
- # @param serializer (see Chan::UNIXSocket#initialize)
14
- # @param sock_type (see Chan::UNIXSocket#initialize)
15
- # @param tmpdir (see Chan::UNIXSocket#initialize)
16
- # @return (see Chan::UNIXSocket#initialize)
17
- def xchan(serializer = :marshal, **kw_args)
18
- Chan::UNIXSocket.new(serializer, **kw_args)
19
- end
20
- end