Mutual exclusion and accept statements

\dlpindex{mutual exclusion} \dlpindex{accept statement} Typically, a counter is used by only one process. When an object is referred to by more than one process, mutual exclusion between the evaluation of goals must be provided, to guarantee that no two processes are simultaneously granted access to a non-logical variable of that object. The example of a semaphore, given below, also shows the need of answer statements to postpone the evaluation of a goal. \Ex 6: semaphore .ds sema.pl The constructor for sema causes the semaphore to loop over a conditional that tests the value of the non-logical variable num. When its value is zero only calls to v() will be answered due to the answer statement answer(v), otherwise both p() and v() may occur, since when num is not zero the answer list is set to $(p,v) by the statement answer(p,v). An instance of sema typically is an active object since it displays own activity in the loop of run. An example of its use is given by
  cs(S,G):- S!p(), G, S!v(). 
  
  :- S = new(sema(1)), ( cs(S,g1) \& cs(S,g2) ).
  
which enforces that the goals g1 and g2 will be executed in a non-overlapping fashion. Since the new semaphore is initialized with one, the first process that asks for
p() must first ask for v() before the other process is granted the evaluation of p(). The need for using a semaphore may arise when mutual exclusion is not effected by using an answer statement for an object containing non-logical variables. Operationally, when an answer statement is reached, the evaluation of the current goal is suspended until a goal allowed by the answer list has been evaluated. When the evaluation of a goal not occurring in the answer list is asked for, the process asking for the evaluation is suspended. The process continues when an answer statement occurs that allows it, and moreover, it is first in the queue of (allowed) processes waiting for the evaluation of a goal. The interplay between processes evaluating a goal and objects to which they commonly refer is rather subtle. It is the object that decides which processes are to be suspended and which processes may be active in evaluating a goal. Only one process may be active in evaluating a goal. It stops being active either upon termination, or by evaluating an answer statement. In both cases that particular object may grant requests for the evaluation of goals, as long as they are allowed by the current answer list. The semaphore defined above may be used to govern the behavior of writers in an implementation of readers-writer protocol, thus allowing multiple readers while forcing writers to wait their turn. In general, unless an answer statement is encountered, an object can display internal concurrency in the sense that multiple processes may be active in evaluating a goal. When an answer statement occurs an object may only handle one request at a time, in a sequential fashion. #ifdef fm_standard .df piece_de_resistance = pi\o"e\(ga"ce de r\o"e\(aa"sistance #else .df piece_de_resistance = pi\`{e}ce de r\'{e}sistance #endif

Dining philosophers

Our piece_de_resistance is an implementation of a solution to the problem of the dining philosophers. Cf.  [Ri88]. Five philosophers must spent their time thinking and eating. When a philosopher wants to eat he must get hold of two forks. Since only five forks are available, each philosopher must await his turn. To avoid the situation where each philosopher sits waiting with one fork, only four philosophers at a time are allowed in the dining room. Since a philosopher needs to know no more than his name, the dining room and his proper forks, after creation he may proceed to enter the cycle of thinking, entering the dining room, picking up his forks, eating and leaving the dining room to start thinking, again. .ds phil.pl A philosopher is admitted to the dining room when less than four guests are present, otherwise he must wait for one of his colleagues to exit. .ds room.pl Forks can only be picked up and then put down. .ds fork.pl The ceremony is started by assigning the philosophers their proper forks and showing them the dining room. The details of their initiation will, for reasons of space, be omitted. The example fully demonstrates the synchronisation enforced by answer statements. Such behavior could not be effected by using simple objects and the synchronous communication construct presented earlier. Much worse, the synchronisation and suspension capability of objects makes such a communication construct superfluous. My personal preference, however, is to use the communication construct in cases where the sophisticated synchronisation provided by the answer statement is not demanded. Communication involving answer statements and non-logical variables is semantically considerably more complex, and seems to preclude a declarative semantics. Apart from this, communication over channels is more efficient.