The previous example showed bidirectional communication, but starts up a new unix process for each request. This can be a reasonable approach, but often we wish to have a subserver handle multiple requests before exiting. This might be because we wish to avoid the overhead of starting up a unix process for each request (at the price of maintaining an open socket), or it might be because we wish to have the server preserve state between calls (we might be using GeomView as a subserver to do 3D graphics display, for example) or it might be because we want to make sure only one copy of the subserver in question is running, either to limit system resources used by the Muq server or to prevent attempts to share an unsharable resource such as a single-user database.
In this example, we show how to set up and access such a server. To keep the example simple, we again have our subserver do nothing more than convert given text to uppercase, but it is still significantly more complex than previous examples.
In muq/srv/
create a file unix-string-upcase-2
with
contents
#!/usr/local/bin/perl select( (select(STDOUT), $| = 1)[0]); while (<STDIN>) { tr/a-z/A-Z/; print; } exit(0);
At the unix level, do the usual
chmod +x unix-string-upcase-2
to make
the script executable.
Now, define the following function in Muq:
nil --> *my-socket* : my-string-upcase-2 { $ -> $ } -> input ( Run as root so normal users ) ( can invoke the subserver: ) asMeDo{ ( Start up subserver if not already running: ) *my-socket* socket? not if makeSocket --> *my-socket* fi *my-socket*$S.type :popen = not if makeLock --> *my-lock* makeMessageStream --> *my-input* makeMessageStream --> *my-output* *my-input* --> *my-socket*$s.standardInput *my-output* --> *my-socket*$s.standardOutput [ :socket *my-socket* :commandline "|unix-string-upcase-2|" | ]rootPopenSocket fi ( Wait until any other copies of us ) ( are finished using the server: ) *my-lock* withLockDo{ ( Send the query to the server: ) input *my-input* writeStream ( Read and return server response: ) *my-output* readStreamLine pop } } ;
You can now do:
root: "abc\n" my-string-upcase-2 root: "ABC " pop "def\n" my-string-upcase-2 root: "DEF "
A subserver like this might well be left running indefinitely, but if you want to shut it down, the usual
[ :socket *my-socket* | ]closeSocket
will suffice.
Go to the first, previous, next, last section, table of contents.