============================================================================
 VX-REXX Tech Note #4:
			                       Introduction to REXX Queues

                                                            March 09, 1994

					 Applies to all versions of VX-REXX
					 
----------------------------------------------------------------------------

                                                       Paul Prescod
                                                       WATCOM International

============================================================================

Abstract
--------

REXX queues are the standard interprocess communication mechanism between
REXX programs.  REXX queues can also be used to pipe the output of 
external programs into a REXX program. This technical note explains when
to use queues, as well as how to create and destroy them.  There is 
more advanced information on the queue interface in the "REXX Information"
reference in the VX-REXX folder.  This document is intended to be used as
an introduction and companion to that reference.

When To Use A REXX Queue
------------------------

Use a REXX queue any time you want to communicate between processes.  
Examples of this would be communication between REXX programs running at
the same time, passing the output of the OS/2 "set" command to a REXX 
program, or sending information from a C program to a REXX program.  Queues 
are system-wide so any REXX application, whether it is Presentation 
Manager based or text mode, foreground, background or detached, can 
access them.

Creating a Queue
----------------

Queue maintanence is done using the RXQueue function.  Queues have names,
just like VX-REXX objects or OS/2 files.  Usually, you will let
REXX choose the queue name:

Qname = RXQueue( "Create" )

Now the variable Qname contains the string that represents the queue, the
queue's name.  This name is usually something along the lines of
"S20Q0363406248." There is nothing special about this string.  It is just
a quasi-random string of letters chosen by REXX used to identify this
queue.  REXX is will always choose a name that is unique system-wide, so you
can be sure that no one else is using that queue.  You can pass that
queue name to any other REXX program, and the two programs can  use the
queue for communications.  You might pass it via a command line
argument, an already existing queue, or a file on disk.

On the other hand, it might be difficult to communicate the queue name
to another program (e.g. one which is already running).  In this case, you 
would want to choose the name of the queue yourself, so you can hard code it 
into both programs when you write them.

    Creating Named Queues
    ------------------
To create a new queue named "Fred", you would say:

Qname = RXQueue( "Create", "Fred" )

If "Fred" did not already exist, REXX will create it, and return the word 
"Fred" (so the variable Qname now contains the word "Fred").


What if Fred Already Exists?
----------------------------

If "Fred" did already exist, REXX will create a new queue, choose its
name, and return it.  Since you have already made the decision to use the
Fred queue, you should immediately delete the new queue.

Be careful, though,  since Fred was already created, there may be another
program using that queue.  Since it is unlikely that two different
developers would choose the same queue name (unless you actually use a
queue named "Fred", which is now world famous!), it is likely that the
queue was created by another copy of your program. Either an earlier 
instance of your program did not destroy the queue, or two instances of 
your program are running concurrently.  Be careful!  It is very easy to 
cross messages.


Using REXX Queues
-----------------

A system can have as many queues as it has memory for, and any particular
REXX program can access as many of them as it wants.  All it has to know
are the names of the queues that it is going to access.  At any one time,
however, there is only one queue that is considered "current". The current
queue is the only one that you can work with.  To use multiple queues, you
change the current queue to each of them in turn.  You can change 
the current queue to any queue whose name you know using the following 
command:

oq = RXQueue( "Set", "Fred" )

Now the current queue is set to the queue "Fred."  The queue name could also
be stored in a variable:

qname = "Fred"
oq = RXQueue( "Set", qname )

Often, instead of setting the variable to a constant, you will use the
variable returned by the "Create" command (above).

qname = RXQueue( "Create" )
oq = RXQueue( "Set", qname )


Sending Data To Queues
----------------------
From REXX
---------
REXX programs use the "Push" and "Queue" commands to put data on the
current queue.  See the "REXX Information" reference for more information
on these functions.

   From the Command Line
   ---------------------
   There is a program in the \OS2 directory called RXQUEUE that allows you to
   send the output of a program to a REXX queue.  Though this command has the
   same name as the RXQueue function, they are in fact different.  RXQUEUE
   is a filter, so you must send data through an OS/2 pipe.  For more 
   information on pipes, see the section called "pipe, using a" in the 
   Master Help Index.  RXQUEUE has the following syntax:
   
   RXQUEUE [Queuename] [/FIFO|/LIFO|/CLEAR],
   
   Queuename is the name of a REXX queue that exists.  

   The /CLEAR parameter removes all text from the queue.
   The /LIFO flag stacks items Last In First Out (like push() ) 
   the /FIFO flag queue items First In First Out (like queue() )
   
   If the queue name is omitted, RXQUEUE uses the contents of the 
   environment variable "RXQUEUE". When the queue name is omitted and 
   the "RXQUEUE" environment variable does not have a value, the RXQUEUE 
   program uses the "SESSION" queue.  For more information on the "SESSION" 
   queue, read the "REXX Information" reference.

   Since commands that can be executed from the command line can also be
   executed from REXX, you can use this technique to pipe the output of an
   external program into your REXX program. For instance, here is a small 
   function which collects the data from the "set" command and sends it to 
   a ListBox.

    /* Set2LB_1: Collects output of set and then puts it in a ListBox
      called LB_1  (if LB_1 does not exist you will get an error message)
    */
    Set2LB_1:
       'set | rxqueue'
       do while queued()>0
	   call VRMethod "LB_1", "AddString", linein("QUEUE:")
       end
    return
   
   This example does not specify a queue because it uses the default queue,
   the "SESSION" queue.  For more information on the queued() function used
   above, see the "REXX Information Reference."  For more information on
   the RXQueue function, see the "Procedures Language 2/REXX Reference" in
   the OS/2 2.0 Technical Library.

   From C
   ------
   There is an undocumented API for accessing a REXX queue from a C program.
   These functions are prototyped in the REXXSAA.H header file. This API is
   not likely to change, but just in case it does, there is also  a
   documented way to write to a REXX queue.  All you have to do is write a
   small REXX program that uses the PUSH command to a buffer in memory, and
   use the RexxStart function to execute it.  There is more information on
   the RexxStart function in the RexxApi.inf reference.


Getting Data From a Queue
---------------------------
Data is retrieved from the queue using the Pull and Linein("QUEUE:")
functions.  These are well documented in the "REXX Information" reference
in the VX-REXX folder.

Destroying REXX Queues
----------------------
You should destroy any REXX Queue you create.  Once the name of the queue is
lost, there is no way to destroy it. To destroy a queue named "Fred", you 
would say:

rc = RXQueue( "Delete", "Fred" )

To destroy a queue whose name is in a variable, qname, you would say:

rc = RXQueue( "Delete", qname )

There is more information about destroying queues and analysing the return
codes in the "REXX Information" reference.

Example Program
----------------

/* Parent.cmd : Simple program showing how to use a REXX Queue */
/* ----------
                Calls a VX-REXX program with a queue name as a parameter
		and then "executes" any commands the VX-REXX program queues.
		Good for modifying the environment of the parent session of
		a VX-REXX program.
*/

qname = rxqueue("Create")

oldqname = rxqueue("Set",qname)

/* Call a VX-REXX program with the queue name as the first parameter
*/
'project.exe' qname

do while queued()>0

    /* Get data out of the queue and execute it as a command
    */
    data = linein("QUEUE:")
    data

end


