@database exec/message ports @author Gregor Goldbach @node main "Exec - Message Ports" The message port is the basis for inter-task communication. It uses @{" signals " link signals.guide/main}, @{" lists " link lists.guide/main}/@{" nodes " link nodes.guide/main} and @{" messages " link messages.guide/main}, read those if you aren't fimiliar with them. @{" Description " link Description} @{" Creation and Deletion " link Creation} @{" Find a public port " link FindPort} @{" Make a port public " link MakePortPublic} @{" How to use it and more " link Important} @{" Where are they used " link WhereAreTheyUsed} There's also an example which shows the use of signals, messages and message ports: @{" Example " link Example} Gregor Goldbach January 24th 1995 @endnode @node Description "Exec - Message Ports -- Description" The message port is defined in @{" exec/ports " rx "AEE:ARexxScripts/ShowModulePart.rexx EMODULES:exec/ports.m 4 10"}. ln:ln This @{" node " link nodes.guide/main} makes it possible to add the message port to a list. In the node's name entry the name of the message port is defined. If other tasks shall be able to find this message port, a name must be specified, s. @{" AddPort() " link MakePortPublic} The type entry has to be set to NT_MSGPORT. flags Defines what happens if a @{" message " link messages.guide/main} arrives at this port. PA_IGNORE msg is ignored, nothing happens PA_SIGNAL the signal from the sigbit entry is sent to the task PA_SOFINT a software interrupt is raised sigbit the number of the @{" signal " link signals.guide/main} which shall be sent to the task if flags=PA_SIGNAL. To wait for this signal you have to make a bit mask for Wait(). Take the number and set its corresponding bit. The usual way to do this is to shift the number 1 x times left (x is the signal number), the function call for this is Shl(1, signal_number). sigtask enter the task which receives the signal from sigbit (flags=PA_SIGNAL), or the address of the software interrupt (flags=PA_SOFTINT) msglist:ln The @{" list " link lists.guide/main} in which the incoming message are put in. Has do be initialized. If a message comes in, it's placed at the end of the list. Gregor Goldbach January 25th 1995 @endnode @endnode Creation "Exec - Message Ports -- Create a message port" To create a message port call port:PTR TO mp := CreateMsgPort() A ready-to-use message port is the result. If you get NIL, something went wrong. This is what this function does: it allocates the memory for the structure, allocates the signal, initializes the list and sets flags to PA_SIGNAL. NOTE: you *MUST* use @{" DeleteMsgPort() " link Deletion} to delete it. To delete a message port created with @{" CreateMsgPort() " link Creation} call DeleteMsgPort(port:PTR TO mp) Gregor Goldbach January 24th 1995 @endnode @node MakePortPublic "Exec - Message Ports -- Put a message port in the public port list" A message port must be put on the public message port list if other tasks shell be able to find it. First you have to fill the name entry of the port's node, then call AddPort(port:PTR TO mp) To remove a port from that list (which has to be done before you delete it), call RemPort(port:PTR TO mp) Gregor Goldbach January 24th 1995 @endnode @node FindPort "Exec - Message Ports -- How to find a public port" A port that has been made public can be found via calling port:PTR TO mp := FindNode(name:PTR TO CHAR) The name argument is the name of the port to search for, it is a string which has to be terminated by 0 (estrings are :) Returns the address of the port if found or NIL. This function should be called to check if a port of that name already exists. Gregor Goldbach January 24th 1995 @endnode @node Important "Exec - Message Ports -- Important notes on usage and more" These are some notes you should remember when using ports. If you're planning to create a public port, first check if a port of that name does already exist via calling @{" FindPort " link FindPort}. If this function returns something other than NIL, the port does exist. Alter the name. If you've added the port to the public port list, you will have to remove it before you delete it. To get messages from a port use this method: Wait() for the signal get all the messages the arrived Wait() again This is the code for it: Wait(signal_mask) WHILE( message := GetMsg(port)) take_action_on_the_message(message) ReplyMsg(message) ENDWHILE Before you delete a port get all the messages that arrived and reply them! Read the last sentence again and remember it well for this is important for the multi-tasking - other tasks may wait for your reply! Gregor Goldbach January 25th 1995 @endnode @node Example "Exec - Message Ports -- An example on message ports" This example consists of two sources/executables: @{" ports1 " system "run SYS:Utilities/MultiView examples/ports1.e"} and @{" ports2 " system "run SYS:Utilities/MultiView examples/ports2.e"}. This is what ports1 does: It open a message port ('port one') and tries to find another port called 'port two'. If this port isn't found, the program will abort, otherwise it sends messages to this port and waits for replies. Its port is then closed. The message's entries are filled after the creation of the port, first the node type, then the reply port and the size of the message (although this doesn't matter here), finally a string is copied in the text entry. Before the next message is sent its contents are changed a bit. Note that only one message is used. This is what port2 does: It opens a port and adds it to the public port list. Since the port from ports1 searches for this port, it is necessary. Then it just waits for messages to arrive, the messages' contents are printed and they're replied. The receiving port will then be removed from the public port list and closed. NOTE: the way the messages are handled is equal to that used in 'real life' programs, e.g. those who wait for inputs in windows. The structure 'special_message': This structure contains the normal message at the beginning. After this an extension is placed: an array of 20 characters. This array is filled by ports1 and printed by ports2. The class entry is used by ports2 to see if it should quit, ports1 sets this entry. Gregor Goldbach January 25th 1995 @endnode @node WhereAreTheyUsed "Exec - Message Ports -- Where are they used?" The message ports can be used to pass any information to another task. This is done by Intuition in IDCMP (Intuition's Direct Communication Message Port). Take an ordinary window. If any events happens, say a mouse-click, Intuition sends a message which holds the information needed to react on it (which mouse button was pressed, at which position was it pressed, when was it pressed etc.). If an application wants to provide an ARexx port it creates a normal message port. The special ARexx-messages contain the needed information. As you can see, the system is very flexible. And now even *you* can use it :-) Gregor Goldbach January 25th 1995 @endnode