Go to the first, previous, next, last section, table of contents.


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

select( (select(STDOUT), $| = 1)[0]);
while (<STDIN>) {

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:   )

        ( 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

        ( 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:

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