xchan.rb 0.16.5 → 0.17.1

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 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