simple-fifo 1.0.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 +7 -0
- data/.gitignore +3 -0
- data/.travis.yml +9 -0
- data/Gemfile +10 -0
- data/README.md +124 -0
- data/Rakefile +14 -0
- data/lib/simple-fifo.rb +13 -0
- data/lib/simple-fifo/fifo.rb +139 -0
- data/simple-fifo.gemspec +18 -0
- metadata +50 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: af466537c7b9bfa49ef532d011a082d3584ba7800a205ad1e591cc44dd10768d
|
4
|
+
data.tar.gz: f3241744fc946f73b932e5c068501fadfcfa5b845832e6a63af89e962de0bc37
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ab15739f205f44920f54efbfad23dea5739c37e260e3af47c0657aac754abaa696dec3deae0d45ec6da902ed2c90fd58a6310348e84065a7e050871018957405
|
7
|
+
data.tar.gz: 9b5244a9b08903a61a8948bf1fc4db114cf686769e4d37107597ab1ab6c94d885ce779c6a142a66bc9961936250e00ab05ece26655a32f687f5e5abf3365339f
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
Forked from ruby-fifo: https://github.com/shurizzle/ruby-fifo
|
2
|
+
|
3
|
+
A small, simple library for using Fifos in Ruby. A Fifo is traditionally a Unix
|
4
|
+
idea that lets processes communicate by writing to and reading from a special
|
5
|
+
kind of file in the filesystem. More information on fifos can be found here:
|
6
|
+
[http://en.wikipedia.org/wiki/Named_pipe](http://en.wikipedia.org/wiki/Named_pipe).
|
7
|
+
|
8
|
+
# Installation
|
9
|
+
|
10
|
+
To install simple-fifo, execute the following command at your terminal:
|
11
|
+
|
12
|
+
$ gem install simple-fifo
|
13
|
+
|
14
|
+
Being sure not to include the dollar sign. The dollar sign is simply convention
|
15
|
+
for denoting a terminal command.
|
16
|
+
|
17
|
+
# Usage
|
18
|
+
|
19
|
+
To use a fifo, you need both a reader and a writer (the POSIX standard does not
|
20
|
+
define the behaviour from using the same file handle as both a reader and a
|
21
|
+
writer so this library does not allow it).
|
22
|
+
|
23
|
+
Here's some example code that will simply write to a fifo and read from it, all
|
24
|
+
in the same process:
|
25
|
+
|
26
|
+
``` ruby
|
27
|
+
reader = Fifo.new('path/to/fifo', :r, :nowait)
|
28
|
+
writer = Fifo.new('path/to/fifo', :w, :nowait)
|
29
|
+
|
30
|
+
writer.puts "Hello, world!"
|
31
|
+
reader.gets
|
32
|
+
#=> "Hello, world!\n"
|
33
|
+
```
|
34
|
+
|
35
|
+
Notice that we pass in `:r` and `:w` for the reader and writer respectively.
|
36
|
+
Also, we have this `:nowait` symbol in there. This tells the library that we
|
37
|
+
don't want to use "blocking" fifos.
|
38
|
+
|
39
|
+
## Blocking vs Non-blocking
|
40
|
+
|
41
|
+
A blocking fifo will block the current thread of execution until the other end
|
42
|
+
is opened. For example, the following code will never finish executing:
|
43
|
+
|
44
|
+
``` ruby
|
45
|
+
reader = Fifo.new('path/to/fifo', :r, :wait)
|
46
|
+
writer = Fifo.new('path/to/fifo', :w, :wait)
|
47
|
+
```
|
48
|
+
|
49
|
+
The thread will be blocked after the first line and it will wait until the
|
50
|
+
writing end of the fifo is opened before allowing execution to continue. This
|
51
|
+
also works exactly the same way in reverse (if you opened the writer before the
|
52
|
+
reader).
|
53
|
+
|
54
|
+
The following code should work fine:
|
55
|
+
|
56
|
+
``` ruby
|
57
|
+
fork do
|
58
|
+
reader = Fifo.new('path/to/fifo', :r, :wait)
|
59
|
+
reader.gets
|
60
|
+
#=> Eventually, this will return "Hello, fork!\n"
|
61
|
+
end
|
62
|
+
|
63
|
+
fork do
|
64
|
+
writer = Fifo.new('path/to/fifo', :w, :wait)
|
65
|
+
writer.puts "Hello, fork!"
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
### Non-blocking
|
70
|
+
|
71
|
+
Alternately, you can use non-blocking pipes. These pipes don't wait for the
|
72
|
+
other end to be open before doing there work. The following code will work just
|
73
|
+
fine all in the same process:
|
74
|
+
|
75
|
+
``` ruby
|
76
|
+
writer = Fifo.new('path/to/fifo', :w, :nowait)
|
77
|
+
writer.puts "Testing"
|
78
|
+
|
79
|
+
reader = Fifo.new('path/to/fifo', :r, :nowait)
|
80
|
+
reader.gets
|
81
|
+
#=> "Testing\n"
|
82
|
+
```
|
83
|
+
|
84
|
+
### Defaults
|
85
|
+
|
86
|
+
Because of this, non-blocking is the default type of fifo that this library will
|
87
|
+
create.
|
88
|
+
|
89
|
+
``` ruby
|
90
|
+
fifo = Fifo.new('path/to/fifo')
|
91
|
+
# This is a non-blocking reader by default
|
92
|
+
```
|
93
|
+
|
94
|
+
## Other methods for reading and writing
|
95
|
+
|
96
|
+
There are other forms of reading and writing that will be familiar to you if you
|
97
|
+
have used the Ruby File object:
|
98
|
+
|
99
|
+
``` ruby
|
100
|
+
reader = Fifo.new('path/to/fifo', :r, :nowait)
|
101
|
+
writer = Fifo.new('path/to/fifo', :w, :nowait)
|
102
|
+
|
103
|
+
writer.puts "Two", "Lines"
|
104
|
+
reader.gets
|
105
|
+
#=> "Two\n"
|
106
|
+
reader.gets
|
107
|
+
#=> "Lines\n"
|
108
|
+
|
109
|
+
writer.print "12345"
|
110
|
+
# reader.gets would block forever here, no new line
|
111
|
+
reader.getc
|
112
|
+
#=> "1"
|
113
|
+
reader.read(1)
|
114
|
+
#=> "2"
|
115
|
+
reader.read(3)
|
116
|
+
#=> "345"
|
117
|
+
|
118
|
+
# reader.read(1)
|
119
|
+
#=> Blocks until something is written
|
120
|
+
|
121
|
+
writer.print "Same as puts\n"
|
122
|
+
reader.readline
|
123
|
+
#=> "Same as puts\n"
|
124
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
|
3
|
+
task :default => [:spec]
|
4
|
+
|
5
|
+
desc "Run all tests."
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
|
8
|
+
desc "Opens up an irb session with the load path and library required."
|
9
|
+
task :console do
|
10
|
+
exec "irb -I lib/ -r ./lib/simple-fifo.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Alias for rake console."
|
14
|
+
task :c => [:console]
|
data/lib/simple-fifo.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
libdir = File.dirname(__FILE__)
|
2
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
3
|
+
|
4
|
+
require 'forwardable'
|
5
|
+
|
6
|
+
if RUBY_PLATFORM =~ /mswin/
|
7
|
+
require 'web32/pipe'
|
8
|
+
$POSIX = false
|
9
|
+
else
|
10
|
+
$POSIX = true
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'simple-fifo/fifo'
|
@@ -0,0 +1,139 @@
|
|
1
|
+
class Fifo
|
2
|
+
# Module to allow delegation
|
3
|
+
include Forwardable
|
4
|
+
|
5
|
+
# Constructs a new Fifo. Can open either a read or write fifo in either
|
6
|
+
# blocking or non-blocking mode.
|
7
|
+
#
|
8
|
+
# Examples:
|
9
|
+
#
|
10
|
+
# # Non-blocking read Fifo (default)
|
11
|
+
# r = Fifo.new('path/to/fifo')
|
12
|
+
#
|
13
|
+
# # Blocking read Fifo
|
14
|
+
# r = Fifo.new('path/to/fifo', :r, :wait)
|
15
|
+
#
|
16
|
+
# # Non blocking write Fifo
|
17
|
+
# w = Fifo.new('path/to/fifo', :w, :nowait)
|
18
|
+
def initialize(file, perms = :r, mode = :nowait)
|
19
|
+
raise 'Unknown file permission. Must be either :r or :w.' unless [:r, :w].include?(perms)
|
20
|
+
|
21
|
+
unless [:wait, :nowait].include?(mode)
|
22
|
+
raise 'Unknown file mode. Must be either :wait or :nowait for blocking' \
|
23
|
+
' or non-blocking respectively.'
|
24
|
+
end
|
25
|
+
|
26
|
+
if $POSIX
|
27
|
+
unless File.exist?(file)
|
28
|
+
File.mkfifo(file)
|
29
|
+
File.chmod(0o0666, file)
|
30
|
+
end
|
31
|
+
|
32
|
+
perms = perms.to_s + (mode == :wait ? '' : '+')
|
33
|
+
@pipe = open_pipe(file, perms)
|
34
|
+
else
|
35
|
+
include Win32
|
36
|
+
|
37
|
+
mode = mode == :wait ? Pipe::WAIT : Pipe::NOWAIT
|
38
|
+
@pipe = perms == :r ? Pipe.new_server(file, mode) : Pipe.new_client(file)
|
39
|
+
@pipe.connect if perms == :r
|
40
|
+
end
|
41
|
+
|
42
|
+
def_delegators :@pipe, :read, :write, :close, :to_io, :flush
|
43
|
+
end
|
44
|
+
|
45
|
+
# Prints the arguments passed in to the fifo. to_s is called on either
|
46
|
+
# argument passed in.
|
47
|
+
#
|
48
|
+
# Example:
|
49
|
+
#
|
50
|
+
# f = Fifo.new('path/to/fifo', :w)
|
51
|
+
# f.print "Hello!"
|
52
|
+
# f.print "Multiple", "Arguments"
|
53
|
+
# f.puts "!" # Need a puts because fifos are line buffered
|
54
|
+
#
|
55
|
+
# r = Fifo.new('path/to/fifo', :r)
|
56
|
+
# r.gets
|
57
|
+
# #=> "Hello!MultipleArugments!\n"
|
58
|
+
def print(*args)
|
59
|
+
args.each do |obj|
|
60
|
+
self.write obj.to_s
|
61
|
+
end
|
62
|
+
|
63
|
+
write $OUTPUT_RECORD_SEPARATOR
|
64
|
+
flush
|
65
|
+
end
|
66
|
+
|
67
|
+
# Works the same as Kernel::puts, writes a string or multiple strings to the
|
68
|
+
# Fifo and then appends a new line. In the case of multiple arguments, a new
|
69
|
+
# line is printed after each one.
|
70
|
+
#
|
71
|
+
# Examples:
|
72
|
+
#
|
73
|
+
# w = Fifo.new('path/to/fifo', :w)
|
74
|
+
# r = Fifo.new('path/to/fifo', :r)
|
75
|
+
#
|
76
|
+
# w.puts "1", "2", "3", "4"
|
77
|
+
#
|
78
|
+
# r.gets
|
79
|
+
# #=> "1\n"
|
80
|
+
#
|
81
|
+
# r.gets
|
82
|
+
# #=> "2\n"
|
83
|
+
#
|
84
|
+
# r.gets
|
85
|
+
# #=> "3\n"
|
86
|
+
#
|
87
|
+
# r.gets
|
88
|
+
# #=> "4\n"
|
89
|
+
def puts(*args)
|
90
|
+
args.each do |obj|
|
91
|
+
self.write "#{obj.to_s.sub(/\n$/, '')}\n"
|
92
|
+
flush
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Reads a single character
|
97
|
+
#
|
98
|
+
# Alias for read(1).
|
99
|
+
def getc
|
100
|
+
self.read(1)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Works in the same way as gets does but uses the $_ global variable for
|
104
|
+
# reading in each character. There is no functional difference between this
|
105
|
+
# and gets.
|
106
|
+
def readline
|
107
|
+
str = ''
|
108
|
+
while ($_ = self.read(1)) != "\n"
|
109
|
+
str << $_
|
110
|
+
end
|
111
|
+
str << "\n"
|
112
|
+
end
|
113
|
+
|
114
|
+
# Reads from the Fifo until it encounters a new line. Will block the current
|
115
|
+
# thread of execution until it hits a new line. This includes when the fifo is
|
116
|
+
# empty and nothing is writing to it.
|
117
|
+
#
|
118
|
+
# Example:
|
119
|
+
#
|
120
|
+
# w = Fifo.new('path/to/fifo', :w)
|
121
|
+
# r = Fifo.new('path/to/fifo', :r)
|
122
|
+
#
|
123
|
+
# w.puts "Hello, world!"
|
124
|
+
# r.gets
|
125
|
+
# #=> "Hello, world!\n"
|
126
|
+
def gets
|
127
|
+
self.readline
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def open_pipe(file, perms)
|
133
|
+
File.open(file, perms)
|
134
|
+
rescue Errno::EINTR
|
135
|
+
# We just want to open a file, so keep retrying.
|
136
|
+
# Inspired by golang's solution: https://github.com/golang/go/commit/50d0ee0c98ea21f818d2daa9bc21ef51861a2ef9
|
137
|
+
retry
|
138
|
+
end
|
139
|
+
end
|
data/simple-fifo.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
Gem::Specification.new { |s|
|
4
|
+
s.name = 'simple-fifo'
|
5
|
+
s.version = '1.0.0'
|
6
|
+
s.author = ['shura', 'jackorp']
|
7
|
+
s.email = 'jar.prokop@volny.cz'
|
8
|
+
s.homepage = 'http://github.com/jackorp/simple-fifo'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.required_ruby_version = '>= 1.9.2'
|
11
|
+
s.summary = 'A cross-platform library to use named pipe'
|
12
|
+
s.description = 'A FIFO library making I/O operations on FIFO files simple.'
|
13
|
+
s.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
14
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
15
|
+
end
|
16
|
+
s.require_path = 'lib'
|
17
|
+
s.has_rdoc = true
|
18
|
+
}
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple-fifo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- shura
|
8
|
+
- jackorp
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2021-06-13 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A FIFO library making I/O operations on FIFO files simple.
|
15
|
+
email: jar.prokop@volny.cz
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- ".travis.yml"
|
22
|
+
- Gemfile
|
23
|
+
- README.md
|
24
|
+
- Rakefile
|
25
|
+
- lib/simple-fifo.rb
|
26
|
+
- lib/simple-fifo/fifo.rb
|
27
|
+
- simple-fifo.gemspec
|
28
|
+
homepage: http://github.com/jackorp/simple-fifo
|
29
|
+
licenses: []
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 1.9.2
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubygems_version: 3.2.15
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: A cross-platform library to use named pipe
|
50
|
+
test_files: []
|