user
Named pipe, or FIFO, is a way of providing inter-process communications (IPC). The task 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:

1. 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;
2. Whenever another process reads the "out" FIFO, it should receive the total count so far.

Possible issues:

* Chances are you don't already have "in" and "out" pipes lying around. Create them within your program or without, at your discretion. You may assume they are already created for you.
* Your program may assume it's the sole reader on "in" and the sole writer on "out".
* Read/write operations on pipes are generally blocking. Make your program responsive to both pipes, so that it won't block trying to read the "in" pipe while leaving another process hanging on the other end of "out" pipe indefinitely -- or vice versa. You probably need to either poll the pipes or use multi-threading.
* You may assume other processes using the pipes behave; specificially, your program may assume the process at the other end of a pipe will not unexpectedly break away before you finish reading or writing.
assistant
|  |
| --- |
| This example is **incorrect**. Please fix the code and remove this message.  ***Details:*** 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.

```
# 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 ½;
}

```

Output:

Terminal 1

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

Terminal 2

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