HELP ACTOR                                           J L Cunningham 1982
                                              Revised John Gibson Aug 93

------------------------------ NOTE ------------------------------------

  From Version 14.5, a change has been made to LIB * ACTOR which makes
  it incompatible with previous versions: the new version has all the
  exported (i.e. top-level) identifiers prefixed by "actor_". In
  addition, LIB EVENT has been replaced by LIB * ACTOR_EVENT, with
  a similar renaming of identifiers.

  Thus you should load these facilities with 'uses actor;' or 'uses
  actor_event;'.

  The old identifier names can be got by loading LIB * OLD_ACTOR or
  LIB * OLD_EVENT, which require LIB * POPOBSOLETELIB first, i.e.

        uses popobsoletelib, old_actor;

  etc.

------------------------------------------------------------------------

The library ACTOR uses the Pop-11 *PROCESS facility to implement basic
procedures for a discrete event simulation package. This can be used for
multi-tasking.

In addition, LIB * ACTOR_EVENT provides an event-handler and associated
procedures, which are described in this help file.

The main user procedures and variables and the terminology used are
described now; the end of this file contains a list of all the other
important global variables and procedures, with a brief description of
what they do.

ACTIVE      At any one moment of real time, only one ACTOR program can
            actually be running (since Pop is a serial language.) Here,
            though, all ACTORs which may become CURRENT without the
            intervention of another ACTOR are referred to as ACTIVE
            (this is not quite standard usage). Basically the ACTIVE
            ACTORs are those that are WAITING plus the CURRENT ACTOR.
            The other actors (those SLEEPING or waiting for an EVENT
            (see ACTOR_WAITEVENT) or waiting to ACTOR_RECEIVE a MESSAGE,
            are not ACTIVE.

ACTOR       When a simulation is started, there will be a number of
            independent (but possibly communicating) "programs" running,
            and possibly multiple copies of the same program. These
            entities are referred to as ACTORS. (An actor is actually
            represented as a RECORD (see HELP *DEFCLASS), one of whose
            components is a pop PROCESS.) In order for actors to
            interact, they each have a name, (see ACTOR_MYNAME) which
            should be unique to that actor.

actor_apocalypse();
            This procedure is run as the final EVENT of a simulation at
            time ACTOR_AEONS. It can be redefined, but there is not much
            point unless you don't like the message it prints.

actor_askactor(<name>,<question>) -> <answer>;
            Runs the named actor's ACTOR_ANSWER procedure, to obtain the
            answer to <question>, but in the context of the <name>d
            actor. So, e.g., it is possible to ask for the values of
            variables local to the <name>d actor.

actor_answer(<question>) -> <answer>;
            This procedure, which should normally be local to individual
            actors, will be run if the actor is asked a <question> by
            another actor. It should NOT call ACTOR_DIE, ACTOR_WAIT or
            ACTOR_SLEEP and it will be unable to ACTOR_ASKACTOR,
            ACTOR_SEND or ACTOR_KILL the actor asking the <question>.
            Since ACTOR_RECEIVE may call ACTOR_SLEEP, it should not call
            ACTOR_RECEIVE unless it knows that there will be a message
            available (see ACTOR_MYMESSAGEQUEUE). The default value of
            this procedure is in the global value of ACTOR_ANSWER and
            always returns the answer 'Dont know', unless the QUESTION
            is a list whose first element is the word "popval", in which
            case the rest of the list is *POPVALed to obtain the answer
            (this is very useful for debugging, see DEBUG.) While
            running ACTOR_ANSWER, all local variables will be as they
            were when the actor answering the question became
            non-CURRENT. Also, CURRENT temporarily becomes the answerer.

actor_aeons
            This constant corresponds to the end of time. It is a large
            number. If an ACTOR does

                        actor_wait(actor_aeons);

            it is likely not to be resumed. This is much like
            ACTOR_SLEEP, but it cannot be woken (but it can still
            ACTOR_ANSWER questions, cf ACTOR_DIE).

CURRENT     The actor currently running is described as CURRENT.

DEBUG       If the pop procedure *POPREADY is included as one of the
            actors at ACTOR_GENESIS, then it can be used for debugging
            purposes. When the POPREADY becomes CURRENT it will prompt
            the terminal as normal. A call of ACTOR_WAIT at this time
            will cause the POPREADY to wait the appropriate amount of
            simulated time before prompting again. Calls of
            ACTOR_ASKACTOR, ACTOR_KILL, ACTOR_NEWACTOR etc. can be used.

actor_die();
            The current actor dies. An actor also dies if the procedure
            which is called when the actor starts returns normally. (If
            ACTOR_DIE is used the actor could be reincarnated if it had
            been saved somewhere; however if the current actor's
            procedure returns normally, it is very dead and cannot be
            reincarnated.)

actor_diewhen(<event>);
            This procedure is in LIB ACTOR_EVENT, and can only be used
            when there is an ACTOR_EVENTHANDLER. It causes the actor
            which calls it to be KILLed when the named <event> (or one
            of the events in the list - cf ACTOR_WAITEVENT) occurs.

EVENT       This word has two meanings. Firstly, every time anything
            occurs, that is an event. Thus, if an actor has WAITed for a
            period (of simulated time), and then it does something, that
            something is an event (cf APOCALYPSE). However, there is a
            more restricted meaning, reserved for particular events
            notified to the ACTOR_EVENTHANDLER.

actor_event(<eventname>,<message>);
            This procedure is in LIB ACTOR_EVENT. If the event
            <eventname> has occurred then this procedure should be
            called, and the ACTOR_EVENTHANDLER will send the <message>
            to any other actors waiting for the event <eventname> (see
            ACTOR_WAITEVENT).

actor_eventhandler();
            This procedure is in LIB ACTOR_EVENT. If the procedures
            ACTOR_EVENT and ACTOR_WAITEVENT are to be used, then the
            word "actor_eventhandler" should be included in the
            ACTOR_GENESIS argument, so that it will be used for an actor
            called "eventhandler1".

actor_exists(<name>);
            Returns true if <name> is NAMEOF an existing actor,
            excluding the current actor. (i.e. in WAITING or SLEEPING).

actor_genesis(<initial>);
            This procedure is used to start a simulation. <initial>
            should be a list of argument lists for ACTOR_NEWACTOR, but
            if the simplest form of call to ACTOR_NEWACTOR is used (i.e.
            with a single argument, a procedure), then the name of the
            procedure (i.e. a Pop variable whose VALOF is the procedure)
            not enclosed in list brackets may be used, and may also be
            preceded by an integer repetition count. (In this case,
            *GENSYM is reset to 1 for that sequence of
            names.) Integers occurring elsewhere in the INITIAL list are
            ignored.

actor_gpo(<name>,<message>,<delay>);
            Defined as

                    actor_newactor(send,[%name,message%],delay)

            This clones the ACTOR_SEND procedure to send the message
            after a delay. The result when the ACTOR_SEND clone returns
            will be erased as it dies irrevocably.

actor_kill(<name>);
            Removes an actor whose NAMEOF is <name> from WAITING or
            SLEEPING; the actor could be reincarnated (cf ACTOR_DIE).

MESSAGE     A MESSAGE can be any Pop data structure. See ACTOR_SEND,
            ACTOR_RECEIVE, ACTOR_GPO, ACTOR_EVENT and ACTOR_WAITEVENT.
            Cf also ACTOR_ASKACTOR and ACTOR_ANSWER.

actor_mymessagequeue
            This is a queue (local to each actor) of messages for the
            current actor to ACTOR_RECEIVE (see HELP *NEWQUEUE). The
            number of messages waiting for the current actor can be
            found by

                queuelength(actor_mymessagequeue) -> <length>;

            The MESSAGEQUEUE is not accessed via this variable name by
            the simulation package, so altering it will have no effect
            (although altering the queue which is its initial value
            will have an effect).

actor_myname
            This is a variable which is local to each actor. Its initial
            value for any actor is the name of that actor. It is useful
            to know this when there are many actors which are copies of
            the same procedure, so that MESSAGES may include a NAME to
            reply to.

actor_myparent
            This is a variable which is local to each actor. It's intial
            value for each actor is the NAME of the actor which created
            that actor, or "eldest" if the actor has no parent (i.e. was
            created at ACTOR_GENESIS).

NAME        To distinguish ACTORs, they each have a name, which should
            be unique. See ACTOR_MYNAME.

actor_newactor(<procedure>[,<actorname>][,<arglist>][,<delay>]);
            ACTOR_NEWACTOR creates a new actor. There are a variety of
            calling formats, summarised above; the arguments in square
            brackets are optional, but if present must appear in the
            order illustrated. <procedure> is the procedure to be run
            for that actor. The first optional argument is the name of
            the actor (a word). If this is omitted, a new name will be
            generated from the *PDPROPS of the procedure, using
            *GENSYM). The second optional argument is a list
            of arguments for the  procedure, and  the third an  optional
            simulation delay before the new actor starts. The list of
            arguments must be a Pop list if present. For an example, see
            ACTOR_GPO.

actor_receive() -> <message>;
            Gets the next message for the current actor. Messages are
            kept in a queue (see HELP *NEWQUEUE). Messages may be put in
            the queue by being SENDed. If the queue is empty, then the
            current actor becomes SLEEPING until there is something in
            the queue. See also ACTOR_SEND, ACTOR_GPO,
            ACTOR_MYMESSAGEQUEUE.

actor_say(<something>);
            Prints <something> on a new line, preceded by the NAMEOF the
            CURRENT actor, and also the time if ACTOR_SAYTIME is TRUE.

actor_saytime
            Global variable. If non-false then ACTOR_SAY will print the
            simulated time.

actor_send(<name>,<message>) -> <boolean>;
            Adds <message> to <name>d actor's queue of messages, and
            WAKEs actor. ACTOR_SEND returns TRUE if <message> has been
            sent successfully, otherwise FALSE (e.g. if no actor exists
            with the specified <name>). An actor cannot ACTOR_SEND a
            message to itself. See also ACTOR_RECEIVE,
            ACTOR_MYMESSAGEQUEUE, ACTOR_GPO.

actor_simtime
            The value of this variable is the current simulation time;
            it should not be explicitly altered by actors. (Really, I
            should make it a procedure without an updater, but I trust
            you.)

actor_sleep();
            The current actor falls asleep, i.e. it becomes inactive. It
            can become active again if WAKEd - cf ACTOR_DIE. Actors
            which are asleep are stored in a variable called SLEEPING.

actor_wait(<duration>);
            The current ACTOR waits, i.e. is suspended, for simulated
            delay given by <duration>. Such actors are stored in a
            variable called WAITING.

                   actor_wait(0);

            will not change the simulated time, but if any other ACTORs
            are WAITING to run at this simulated time, then the current
            actor will be suspended. If more than one ACTOR is due to
            become CURRENT at the same simulated time, then the one that
            began waiting at the earliest real time becomes CURRENT.

actor_wake(<name>);
            Wake, i.e. make ACTIVE, the actor whose name is <name> (it
            will become CURRENT at the present simulated time, after any
            other ACTORs at this time). ACTOR_WAKE has no effect if
            there is no such actor in SLEEPING.

actor_waitevent(<event>) -> <message>;
            This procedure is in LIB ACTOR_EVENT. When it is called, it
            tells the ACTOR_EVENTHANDLER that the current actor is now
            waiting for the <event> (a word) or alternatively any of the
            events in <event> (a list of words). The procedure returns
            with the <message> associated with the <event> when it
            occurs.

-----------------------------------------------------------------------

Some procedures and variables used internally to the simulation package,
but which might be useful to hackers. They are in section $-actor.

current     current actor
waiting     the actors active but not current
sleeping    the actors sleeping
find(<name>,<chain>);
            might be useful to a hacker, but look at the source code
nameof(<actor>);
waketime(<actor>);
            the time a waiting actor is due to become current
nextactor(<actor>);
            link to next actor when in a chain
processof(<actor>);
            might be useful to resume simulation, e.g. by
              resume(0,processof(<current>))
practor(<actor>);
            used to print an actor or chain of actors
schedule(<time>,<actor>);
            adds <actor> to WAITING with <time> as its waketime
parentof(<actor>);
            the NAMEOF the actor which created the <actor> (which is
            the argument to PARENTOF), or else "eldest" for actors
            created at ACTOR_GENESIS
messagequeue(<actor>);
            The queue used for storing <actor>'s unprocessed messages
returnanswer(<question>);
            This procedure is part of the question answering
            mechanism, and should not be called by actors.

See also
HELP *AUTOLOAD - on the automatic compilation of library files
HELP *NEWQUEUE - library procedure for creating queues
HELP *PROCESS  - summary of the Pop-11 PROCESS facility
HELP *POPVAL   - evaluates list items as Pop-11 code
HELP *POPREADY - invokes compiler recursively. Useful for interrupts
SHOWLIB *ACTOR - for the program code


--- C.all/help/actor
--- Copyright University of Sussex 1992. All rights reserved. ----------
