$=

An asynchronous rendez-vous mechanism

\label{des/ext/proc} The rendez-vous presented consists of two parts, the creation of a process to evaluate a method call and the request for an answer. For creation of the evaluating process, one may use the special statement \dlpindex{\rendezexpr} to request the object to which O refers to create a process to evaluate the goal
m(t). The variable Q thereafter refers to that process. For the request of the result we introduce \dlpindex{\resumeexpr} that asks the process, referred to by Q, for an (other) answer.

Informal semantics

\nop{ The semantics of these statements can be easily explained by remarking that the method call
O!m(t) may considered to be implemented as O!m(t) :- Q = O!m(t), Q?. However there are some intricacies, notably with respect to the backtracking behavior. First however we will motivate the usefulness of these extensions. } Using somewhat contradictory terminology, a call of the form Q = O!m(t) may be regarded as an asynchronous method call, since receiving the (possibly multiple) answers requires an explicit request of the form Q?. The variable Q is bound to a pointer to the process evaluating m(t). The method call m(t) must explicitly be accepted by an accept goal of the object to which O refers. We call the goal Q? a resumption request, since it delivers a resumption containing the answer substitutions that result from the call. Evaluating the resumption enables the possible variable bindings of these answers to take effect in the current context. The decomposition of a method call in the request of evaluation and the request of a result allows the programmer to achieve extra parallelism, since the newly created process runs independently of the invoking process, which does not have to wait for an answer. Such overlapping of processes is expressed by a goal of the form [] Q = O!m(t), G, Q? Between the creation of the process evaluating the goal m(t) and stating the resumption request to collect the answers to m(t), the invoking process can perform any action whatsoever. .so and The asynchronous rendez-vous preserves completeness in coupling the solutions produced by evaluating m(t) with the bindings resulting from the evaluation of G. When backtracking occurs each alternative binding resulting from the evaluation of G must be coupled with all possible solutions of m(t). However, if m(t) has infinitely many solutions, G will never be tried for producing alternative bindings.

And parallelism

The decomposition of the rendez-vous allows to define and-parallelism in a rather straightforward way, as \dlpindex{\andexpr} A\&B :- Q = self ! B, A, Q?. where self refers to the object evaluating the goal
A \& B . Such goals may however occur only in passive objects, since only passive objects allow internal concurrency. \nop{ A typical example of the use of this kind of parallelism is the following, familiar, quicksort program. \lprog{qsort}{ .ds qsort.pl } Each nonempty list is divided into two sublists, one with values less than the values in the other. These are then sorted in parallel and the sorted sublists are concatenated. } An advantage of this approach is that the programmer may restrict the cases where parallel evaluation occurs by imposing extra conditions (cf.  [DG84]) as in
  A\&B :- ground(B),!, Q = self ! B, A, Q?. 
  A\&B :- A, B.
  
where splitting of a new process is allowed only when B is ground. Note that the cut in the first clause is used to avoid unwanted backtracking over the second solution of {\small A\&B}. \nop{ As a shortcoming, however, we must note that there is a certain incompleteness with respect to the solutions for A and B in a goal sequence of the form
Q = O!A, B, Q?. Since the meaning of Q? is by default attuned to its use in implementing the synchronous rendez-vous, Q? explores all answer substitutions resulting from the evaluation of a goal and thereafter returns failure. B and A are generated but only the solutions composed of the first solution for B with any solution for A. }

Example

A typical example of the use of this kind of parallelism is the following, familiar, quicksort program. \lprog{qsort}{ .ds qsort.pl } Each non-empty list is divided into two sublists, one with values less than the values in the other. These are then sorted in parallel and the sorted sublists are concatenated.