IPC via named pipe: Difference between revisions

Added FreeBASIC
(Added Wren)
(Added FreeBASIC)
 
(5 intermediate revisions by 2 users not shown)
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}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 177 ⟶ 227:
output.Close()
}
}</langsyntaxhighlight>
 
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight Perllang="perl"># 20200924 added Perl programming solution
 
use strict;
Line 214 ⟶ 264:
}
sleep .5;
}</langsyntaxhighlight>
{{out}}
Terminal 1
Line 241 ⟶ 291:
 
=={{header|Phix}}==
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\IPC_via_named_pipe.exw
Line 322 ⟶ 372:
<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>
<!--</langsyntaxhighlight>-->
{{out}}
After letting it run for about 5s before hitting escape, on separate terminal windows:
Line 337 ⟶ 387:
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(call 'mkfifo "in" "out") # Create pipes
 
(zero *Cnt) # Initialize byte counter
Line 356 ⟶ 406:
 
(push '*Bye '(call 'rm "in" "out")) # Remove pipes upon exit
(wait) # (Terminate with Ctrl-C)</langsyntaxhighlight>
Test:
<pre>$ line <out
Line 368 ⟶ 418:
 
=={{header|Racket}}==
<langsyntaxhighlight Racketlang="racket">#lang racket
 
(define-values (in out) (make-pipe))
Line 391 ⟶ 441:
 
(thread-wait t1)
(thread-wait t2)</langsyntaxhighlight>
 
=={{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" perl6line># 20200923 Added Raku programming solution
 
use NativeCall;
Line 429 ⟶ 479:
}
sleep ½;
}</langsyntaxhighlight>
{{out}}
Terminal 1
Line 459 ⟶ 509:
{{works with|Unix}}
 
<langsyntaxhighlight lang="ruby">require 'socket'
 
# Ruby has no direct access to mkfifo(2). We use a shell script.
Line 519 ⟶ 569:
end
end
end</langsyntaxhighlight>
 
Example run:
Line 537 ⟶ 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 568 ⟶ 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.
Although this solution is loosely based on the C entry, it is single-threaded and uses two fibers for the read and write loops which yield to each other after each iteration. The 'read' fiber runs first so that the 'write' fiber won't block.
 
This works fine on Ubuntu 20.04 and should work on other Linux distros though I can't vouch for anything else.
<langsyntaxhighlight ecmascriptlang="wren">/* ipc_via_named_pipeIPC_via_named_pipe.wren */
 
var inputFifoInputFifo = "in"
var outputFifoOutputFifo = "out"
 
var O_RDONLY = 0
Line 585 ⟶ 637:
 
var PIPE_BUF = 4096
 
var Tally = 0
 
class Fifo {
Line 602 ⟶ 652:
}
 
class C {
var readLoop = Fn.new {
whileforeign static usleep(trueusec) {
 
var fd = File.open(inputFifo, O_RDONLY)
foreign static var lentally
foreign static tally=(newTally)
while ((len = File.read(fd, PIPE_BUF)) > 0) Tally = Tally + len
File.close(fd)
Fiber.yield()
}
}
 
class Loops {
var writeLoop = Fn.new {
whilestatic read(true) {
varwhile fd = File.open(outputFifo,true) O_WRONLY){
var tsfd = TallyFile.toString +open(InputFifo, "\n"O_RDONLY)
File.write(fd, ts, ts.bytes.count) var len
while ((len = File.closeread(fd, PIPE_BUF)) > 0) C.tally = C.tally + len
Fiber File.yieldclose(fd)
}
}
}
 
static write() {
Fifo.make(inputFifo, 438)
while (true) {
Fifo.make(outputFifo, 438)
var fd = File.open(OutputFifo, O_WRONLY)
 
var ts = C.tally.toString + "\n"
var rf = Fiber.new(readLoop)
File.write(fd, ts, ts.bytes.count)
var wf = Fiber.new(writeLoop)
File.close(fd)
C.usleep(10000)
}
}
}
 
Fifo.make(InputFifo, 438)
while (true) {
Fifo.make(OutputFifo, 438)</syntaxhighlight>
rf.call()
wf.call()
}</lang>
<br>
We now embed this script in the following C program, build and run from one terminal.
<langsyntaxhighlight lang="c">/* gcc ipc_via_named_pipeIPC_via_named_pipe.c -o ipc_via_named_pipeIPC_via_named_pipe -lpthread -lwren -lm */
 
#include <stdio.h>
Line 642 ⟶ 692:
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include "wren.h"
 
// #include <errno.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);
Line 685 ⟶ 736:
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;
}
 
Line 695 ⟶ 761:
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;
Line 734 ⟶ 804:
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);
}
 
Line 742 ⟶ 830:
config.errorFn = &errorFn;
config.bindForeignMethodFn = &bindForeignMethod;
WrenVM* vm = wrenNewVM(&config);
vm2 = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "ipc_via_named_pipeIPC_via_named_pipe.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
Line 757 ⟶ 846:
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;
}</langsyntaxhighlight>
<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
Line 776 ⟶ 872:
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}}
<langsyntaxhighlight lang="zkl">pipe:=Thread.Pipe(); // NOT a Unix pipe, for inter-thread commication
fcn writeLoop(pipe){ // a thread
out:=File("out","w");
Line 793 ⟶ 889:
}.launch(pipe);
 
while(1){ Atomic.sleep(10000); } // veg out while other talk</langsyntaxhighlight>
{{out}}
Terminal 1:
2,169

edits