IPC via named pipe: Difference between revisions

Added FreeBASIC
(→‎{{header|C}}: If WILL_BLOCK_EVERYTHING, then prevent the "in" pipe blocking everything.)
(Added FreeBASIC)
 
(19 intermediate revisions by 10 users not shown)
Line 1:
{{draft task}}
[[wp:Named pipe|Named pipe]], or FIFO, is a way of providing inter-process communications (IPC). The Totask is to demonstrate how it works, create two pipes, say, "in" and "out" (choose suitable names for your system), and write a program that works the two pipes such that:
# Data written to the "in" FIFO will be discarded except the byte count, which will be added to a total tally kept by the program;
# Whenever another process reads the "out" FIFO, it should receive the total count so far.
Line 12:
=={{header|C}}==
{{libheader|pthread}}
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
Line 102:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="vbnet">#Include "file.bi"
 
Type FileInfo
As String path
As Integer oflag
End Type
 
Function OpenFile(file As FileInfo) As Integer
Dim As Integer f = Freefile
Open file.path For Binary Access Read Write As #f
If Lof(f) > 0 Then
Print "Error opening file"
Return -1
End If
Return f
End Function
 
Function ReadFromFile(f As Integer, Byref buf As String, size As Integer) As Integer
Get #f, , buf
Return Len(buf)
End Function
 
Sub WriteToFile(f As Integer, buf As String, size As Integer)
Put #f, , buf
End Sub
 
Dim As FileInfo inputFile
inputFile.path = "in.fifo"
inputFile.oflag = 0
 
Dim As FileInfo outputFile
outputFile.path = "out.fifo"
outputFile.oflag = 1
 
Dim As Integer entrada = OpenFile(inputFile)
Dim As Integer salida = OpenFile(outputFile)
 
If entrada = -1 Or salida = -1 Then
Print "Error opening files"
End
End If
 
Dim As String buffer
Dim As Integer bytesRead
Do
bytesRead = ReadFromFile(entrada, buffer, 64)
If bytesRead > 0 Then WriteToFile(salida, buffer, bytesRead)
Loop</syntaxhighlight>
 
=={{header|Go}}==
<syntaxhighlight lang="go">package main
 
import (
"fmt"
"io"
"log"
"os"
"sync/atomic"
"syscall"
)
 
const (
inputFifo = "/tmp/in.fifo"
outputFifo = "/tmp/out.fifo"
readsize = 64 << 10
)
 
func openFifo(path string, oflag int) (f *os.File, err error) {
err = syscall.Mkfifo(path, 0660)
// We'll ignore "file exists" errors and assume the FIFO was pre-made
if err != nil && !os.IsExist(err) {
return
}
f, err = os.OpenFile(path, oflag, 0660)
if err != nil {
return
}
// In case we're using a pre-made file, check that it's actually a FIFO
fi, err := f.Stat()
if err != nil {
f.Close()
return nil, err
}
if fi.Mode()&os.ModeType != os.ModeNamedPipe {
f.Close()
return nil, os.ErrExist
}
return
}
 
func main() {
var byteCount int64
go func() {
var delta int
var err error
buf := make([]byte, readsize)
for {
input, err := openFifo(inputFifo, os.O_RDONLY)
if err != nil {
break
}
for err == nil {
delta, err = input.Read(buf)
atomic.AddInt64(&byteCount, int64(delta))
}
input.Close()
if err != io.EOF {
break
}
}
log.Fatal(err)
}()
 
for {
output, err := openFifo(outputFifo, os.O_WRONLY)
if err != nil {
log.Fatal(err)
}
cnt := atomic.LoadInt64(&byteCount)
fmt.Fprintln(output, cnt)
output.Close()
}
}</syntaxhighlight>
 
=={{header|Perl}}==
{{trans|Raku}}
<syntaxhighlight lang="perl"># 20200924 added Perl programming solution
 
use strict;
use warnings;
 
use File::Temp qw/ :POSIX /;
use POSIX qw/ mkfifo /;
use Fcntl;
 
my ($in, $out) = map { scalar tmpnam() } 0,1 ;
 
for ($in, $out) { mkfifo($_,0666) or die $! };
 
print "In pipe : $in\nOut pipe : $out\n";
 
my $CharCount = 0 ;
 
$SIG{INT} = sub {
for ($in, $out) { unlink $_ or die }
print "\nTotal Character Count: $CharCount\nBye.\n" and exit
};
 
sysopen( IN, $in, O_NONBLOCK|O_RDONLY ) or die;
sysopen( OUT, $out, O_NONBLOCK|O_RDWR ) or die;
 
while (1) {
sysread(IN, my $buf, 32); # borrowed the buffer size from the c entry
if ( length $buf > 0 ) {
$CharCount += length $buf;
while (sysread(OUT, $buf, 1)) {} ; # empty the write pipe
syswrite( OUT, $CharCount ) or die;
}
sleep .5;
}</syntaxhighlight>
{{out}}
Terminal 1
<pre>In pipe : /tmp/0oPaYmkOI2
Out pipe : /tmp/DdWOGVOaBI
^C
Total Character Count: 7083641
Bye.</pre>
Terminal 2
<pre>echo asdf > /tmp/0oPaYmkOI2
cat /tmp/DdWOGVOaBI
5^C
echo qwer > /tmp/0oPaYmkOI2
echo uiop > /tmp/0oPaYmkOI2
cat /tmp/DdWOGVOaBI
15^C
wc /etc/passwd
33 63 1642 /etc/passwd
cat /etc/passwd > /tmp/0oPaYmkOI2
cat /tmp/DdWOGVOaBI
1657^C
cat /dev/urandom > /tmp/0oPaYmkOI2
^C
cat /tmp/DdWOGVOaBI
7083641^C</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\IPC_via_named_pipe.exw
-- ===================================
--
-- Note: uses a single bidirectional pipe, Windows only, and no attempt has been
-- made to avoid blocking, this sort of code should be put in a separate thread.
--
-- Running normally starts this as a server which automatically creates a client.
--
-- Several additional Windows-only routines have been added to builtins/pipeio.e
-- which will not be formally documented until they are fully Linux-compatible.
--</span>
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1.0.1"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #004600;">WINDOWS</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (obviously this will never ever run in a browser!)</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">/</span><span style="color: #000000;">pipeio</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">szPipename</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">`\\.\pipe\mynamedpipe`</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">cl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">command_line</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">rand_string</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">100</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand_range</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'Z'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"-client"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Server\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">dwPipeMode</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">or_all</span><span style="color: #0000FF;">({</span><span style="color: #000000;">PIPE_TYPE_MESSAGE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PIPE_READMODE_MESSAGE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PIPE_WAIT</span><span style="color: #0000FF;">}),</span>
<span style="color: #000000;">totalsofar</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">pBuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1024</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">pBytesRead</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">pBytesWritten</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">hPipe</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">create_named_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">szPipename</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PIPE_ACCESS_DUPLEX</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dwPipeMode</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">system_exec</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`"%s" "%s" -client`</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">),</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">connect_named_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">read_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pBuffer</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1024</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pBytesRead</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">res</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nsleep??\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.25</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bytesread</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">peek4s</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pBytesRead</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">peek</span><span style="color: #0000FF;">({</span><span style="color: #000000;">pBuffer</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bytesread</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bytesread</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span> <span style="color: #008080;">and</span> <span style="color: #000000;">msg</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"quit"</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nquit recieved, quitting\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">totalsofar</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">bytesread</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"bytesread:%,d total so far:%,d "</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">bytesread</span><span style="color: #0000FF;">,</span><span style="color: #000000;">totalsofar</span><span style="color: #0000FF;">})</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">reply</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%,d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">totalsofar</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">write_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">,</span><span style="color: #000000;">reply</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pBytesWritten</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">res</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">peek4s</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pBytesWritten</span><span style="color: #0000FF;">)!=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">reply</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">flush_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">disconnect_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">free</span><span style="color: #0000FF;">({</span><span style="color: #000000;">pBytesWritten</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pBuffer</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pBytesRead</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">close_handle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Client\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Press Escape or Q to quit\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">running_total</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">get_key</span><span style="color: #0000FF;">(),{</span><span style="color: #008000;">'q'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'Q'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#1B</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rand_string</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">reply</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">call_named_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">szPipename</span><span style="color: #0000FF;">,</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">running_total</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">bOK</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">reply</span><span style="color: #0000FF;">==</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%,d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">running_total</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"set %d bytes, reply:%s, running_total:%,d (same:%t)"</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">reply</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">running_total</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bOK</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">bOK</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nsome error, quitting...\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">call_named_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">szPipename</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"quit"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
{{out}}
After letting it run for about 5s before hitting escape, on separate terminal windows:
<pre>
Server
bytesread:19 total so far:2,136,798
quit recieved, quitting
 
Client
Press Escape or Q to quit
set 19 bytes, reply:2,136,798, running_total:2,136,798 (same:true)
</pre>
 
 
=={{header|PicoLisp}}==
<syntaxhighlight lang="picolisp">(call 'mkfifo "in" "out") # Create pipes
 
(zero *Cnt) # Initialize byte counter
 
(unless (fork) # Handle "out" pipe
(loop
(out "out"
(sync)
(tell)
(prinl *Cnt) ) ) )
 
(unless (fork) # Handle "in" pipe
(let P (open "in")
(loop
(in P # Open twice, to avoid broken pipes
(while (rd 1) # (works on Linux, perhaps not POSIX)
(tell 'inc ''*Cnt) ) ) ) ) )
 
(push '*Bye '(call 'rm "in" "out")) # Remove pipes upon exit
(wait) # (Terminate with Ctrl-C)</syntaxhighlight>
Test:
<pre>$ line <out
0
$ echo abc >in
$ line <out
4
$ echo äöü >in
$ line <out
11</pre>
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">#lang racket
 
(define-values (in out) (make-pipe))
 
;; Thread loops through list of strings to send
;; and closes port when finished
(define t1 (thread (lambda ()
(for ([i (list "a" "test" "sequence")])
(display i out)
(sleep 1))
(close-output-port out))))
 
;; Blocking call to read char, if not EOF then loop
(define t2 (thread (lambda ()
(define cnt 0)
(let loop ()
(when (not (eof-object? (read-char in)))
(set! cnt (add1 cnt))
(loop)))
(display (format "Bytes Rx: ~a\n" cnt))
(close-input-port in))))
 
(thread-wait t1)
(thread-wait t2)</syntaxhighlight>
 
=={{header|Raku}}==
{{incorrect|Raku| Blocks on the read pipe and not able to empty/update the write pipe according to the task requirement }}
Couldn't figure out how to get around the IO blockages as per the talk page so any help would be appreciated, thanks in advance.
<syntaxhighlight lang="raku" line># 20200923 Added Raku programming solution
 
use NativeCall;
use UUID; # cannot mix File::Temp with mkfifo well so use this as tmpnam
 
my ($in, $out) = <in out>.map: { "/tmp/$_-" ~ UUID.new } ;
 
sub mkfifo(Str $pathname, int32 $mode --> int32) is native('libc.so.6') is symbol('mkfifo') {*}
 
($in,$out).map: { die $!.message if mkfifo($_, 0o666) } ; # c style exit code
 
say "In pipe: ", $in;
say "Out pipe: ", $out;
 
my atomicint $CharCount = 0;
 
signal(SIGINT).tap: {
($in,$out).map: { .IO.unlink or die } ;
say "\nBye." and exit;
}
 
loop {
given $in.IO.watch { # always true even when nothing is spinning ?
 
say "Current count: ", $CharCount ⚛+= $in.IO.open.readchars.codes;
 
given $out.IO.open(:update :truncate) { # both truncate and flush aren't
.flush or die ; # working on pipes so without a
.spurt: "$CharCount\t" # prior consumer it just appends
}
$out.IO.open.close or die;
}
sleep ½;
}</syntaxhighlight>
{{out}}
Terminal 1
<pre>named-pipe.raku
In pipe: /tmp/in-b49e4cdf-80b6-49da-b4a3-2810f1eeeb6a
Out pipe: /tmp/out-44fcd0db-ce02-47b4-bdd3-34833f3dd621
Current count: 5
Current count: 10
Current count: 15
^C
Bye.</pre>
Terminal 2
<pre>echo asdf > /tmp/in-b49e4cdf-80b6-49da-b4a3-2810f1eeeb6a
cat /tmp/out-44fcd0db-ce02-47b4-bdd3-34833f3dd621
5 ^C
echo qwer > /tmp/in-b49e4cdf-80b6-49da-b4a3-2810f1eeeb6a
echo uiop > /tmp/in-b49e4cdf-80b6-49da-b4a3-2810f1eeeb6a
cat /tmp/out-44fcd0db-ce02-47b4-bdd3-34833f3dd621
10 15 ^C</pre>
 
=={{header|Ruby}}==
Line 114 ⟶ 509:
{{works with|Unix}}
 
<langsyntaxhighlight lang="ruby">require 'socket'
 
# Ruby has no direct access to mkfifo(2). We use a shell script.
Line 174 ⟶ 569:
end
end
end</langsyntaxhighlight>
 
Example run:
Line 192 ⟶ 587:
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl"># Make the pipes by calling a subprocess...
exec sh -c {test -p in || mkfifo in || exit 1;test -p out || exec mkfifo out}
 
Line 223 ⟶ 618:
 
# Run the event loop until done
vwait forever</langsyntaxhighlight>
 
=={{header|Wren}}==
{{trans|C}}
{{libheader|pthread}}
An embedded program using a C host as Wren has no built in support for named pipes.
 
As in the case of the C example, we run the 'write' loop on a separate thread and using a separate VM. The 'tally' variable is stored on the C side so it can be shared by both VM's.
 
This works fine on Ubuntu 20.04 and should work on other Linux distros though I can't vouch for anything else.
<syntaxhighlight lang="wren">/* IPC_via_named_pipe.wren */
 
var InputFifo = "in"
var OutputFifo = "out"
 
var O_RDONLY = 0
var O_WRONLY = 1
 
var PIPE_BUF = 4096
 
class Fifo {
foreign static make(path, oflag)
}
 
class File {
foreign static open(path, flags)
 
foreign static write(fd, str, size)
 
foreign static read(fd, size)
 
foreign static close(fd)
}
 
class C {
foreign static usleep(usec)
 
foreign static tally
foreign static tally=(newTally)
}
 
class Loops {
static read() {
while (true) {
var fd = File.open(InputFifo, O_RDONLY)
var len
while ((len = File.read(fd, PIPE_BUF)) > 0) C.tally = C.tally + len
File.close(fd)
}
}
 
static write() {
while (true) {
var fd = File.open(OutputFifo, O_WRONLY)
var ts = C.tally.toString + "\n"
File.write(fd, ts, ts.bytes.count)
File.close(fd)
C.usleep(10000)
}
}
}
 
Fifo.make(InputFifo, 438)
Fifo.make(OutputFifo, 438)</syntaxhighlight>
<br>
We now embed this script in the following C program, build and run from one terminal.
<syntaxhighlight lang="c">/* gcc IPC_via_named_pipe.c -o IPC_via_named_pipe -lpthread -lwren -lm */
 
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include "wren.h"
 
/* C <=> Wren interface functions */
 
size_t tally = 0;
 
void C_make(WrenVM* vm) {
const char *pathname = wrenGetSlotString(vm, 1);
mode_t mode = (mode_t)wrenGetSlotDouble(vm, 2);
int res = mkfifo(pathname, mode);
wrenSetSlotDouble(vm, 0, (double)res);
}
 
void C_open(WrenVM* vm) {
const char *pathname = wrenGetSlotString(vm, 1);
int flags = (int)wrenGetSlotDouble(vm, 2);
int fd = open(pathname, flags);
if (fd < 0) {
perror(NULL);
}
wrenSetSlotDouble(vm, 0, (double)fd);
}
 
void C_write(WrenVM* vm) {
int fd = (int)wrenGetSlotDouble(vm, 1);
const char *str = wrenGetSlotString(vm, 2);
size_t count = (size_t)wrenGetSlotDouble(vm, 3);
ssize_t res = write(fd, (const void *)str, count + 1);
wrenSetSlotDouble(vm, 0, (double)res);
}
 
void C_read(WrenVM* vm) {
int fd = (int)wrenGetSlotDouble(vm, 1);
size_t nbyte = (size_t)wrenGetSlotDouble(vm, 2);
char buf[nbyte];
ssize_t res = read(fd, buf, nbyte);
wrenSetSlotDouble(vm, 0, (double)res);
}
 
void C_close(WrenVM* vm) {
int fd = (int)wrenGetSlotDouble(vm, 1);
int res = close(fd);
wrenSetSlotDouble(vm, 0, (double)res);
}
 
void C_usleep(WrenVM* vm) {
useconds_t usec = (useconds_t)wrenGetSlotDouble(vm, 1);
int res = usleep(usec);
wrenSetSlotDouble(vm, 0, (double)res);
}
 
void C_getTally(WrenVM* vm) {
wrenSetSlotDouble(vm, 0, (double)tally);
}
 
void C_setTally(WrenVM* vm) {
size_t newTally = (size_t)wrenGetSlotDouble(vm, 1);
tally = newTally;
}
 
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Fifo") == 0) {
if (isStatic && strcmp(signature, "make(_,_)") == 0) return C_make;
} else if (strcmp(className, "File") == 0) {
if (isStatic && strcmp(signature, "open(_,_)") == 0) return C_open;
if (isStatic && strcmp(signature, "write(_,_,_)") == 0) return C_write;
if (isStatic && strcmp(signature, "read(_,_)") == 0) return C_read;
if (isStatic && strcmp(signature, "close(_)") == 0) return C_close;
} else if (strcmp(className, "C") == 0) {
if (isStatic && strcmp(signature, "usleep(_)") == 0) return C_usleep;
if (isStatic && strcmp(signature, "tally") == 0) return C_getTally;
if (isStatic && strcmp(signature, "tally=(_)") == 0) return C_setTally;
}
}
return NULL;
}
 
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
 
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
 
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
 
WrenVM *vm, *vm2;
 
void read_loop() {
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "main", "Loops", 0);
WrenHandle *method = wrenMakeCallHandle(vm, "read()");
wrenCall(vm, method);
wrenReleaseHandle(vm, method);
}
 
void* write_loop(void *a) {
wrenEnsureSlots(vm2, 1);
wrenGetVariable(vm2, "main", "Loops", 0);
WrenHandle *method = wrenMakeCallHandle(vm2, "write()");
wrenCall(vm2, method);
wrenReleaseHandle(vm2, method);
}
 
int main(int argc, char **argv) {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignMethodFn = &bindForeignMethod;
vm = wrenNewVM(&config);
vm2 = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "IPC_via_named_pipe.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenInterpret(vm2, module, script);
pthread_t pid;
pthread_create(&pid, 0, write_loop, 0);
read_loop();
wrenFreeVM(vm);
wrenFreeVM(vm2);
free(script);
return 0;
}</syntaxhighlight>
<br>
{{out}}
Finally we can test that this is working correctly by typing in the following commands from a different terminal. The string lengths returned will, of course, include the final zero byte.
<pre>
$ cat out
0
$ echo test > in
$ cat out
5
$ echo "named pipe" > in
$ cat out
16
</pre>
 
=={{header|zkl}}==
zkl doesn't open pipes but it knows about them (on Unix anyway as they are just a file). So, outside of the program, create two named pipes and read/write to them inside the program.
{{trans|C}}
<syntaxhighlight lang="zkl">pipe:=Thread.Pipe(); // NOT a Unix pipe, for inter-thread commication
fcn writeLoop(pipe){ // a thread
out:=File("out","w");
foreach tally in (pipe){ out.writeln(tally); out.flush(); }
println("writeLoop done");
}.launch(pipe);
 
fcn readLoop(pipe){ // a thread
tally:=0;
in:=File("in","r").howza(3); // open for read, reading characters
while(1){ // named pipe sets EoF after writer exits
foreach c in (in){ pipe.write(tally+=1) } // read bytes until EoF
}
in.close();
println("readLoop done");
}.launch(pipe);
 
while(1){ Atomic.sleep(10000); } // veg out while other talk</syntaxhighlight>
{{out}}
Terminal 1:
<pre>
$ mkfifo in; mkfifo out
<wait until other two terminals get going>
$ echo "hello world" > in
$ cat ../Tests/lorem_ipsum.txt >in
</pre>
{{out}}
In Terminal 2, start the program:
<pre>$ zkl bbb</pre>
{{out}}
Terminal 3:
There is pretty much no delay - character enters "in", "out" sees tally.
<pre>
$ cat out
1
2
3
4
5
6
7
8
9
10
11
12
...
1391
1392
1393
1394
1395
1396
1397
1398
1399
</pre>
 
{{omit from|GUISS}}
{{omit from|Mathematica}}
{{omit from|ZX Spectrum Basic}}
2,139

edits