next up previous contents index
Next: GNAT Implementation Up: The Rendezvous Previous: The Rendezvous   Contents   Index


The Ada Rendezvous

Entry Declaration

Each entry identifies the name of the service, the parameters that are required with the request and the results that will be returned [BW98, section 5.1]. The Ada Reference Manual defines the syntax as follows [AAR95, section 9.5.2]:

entry_declaration ::=
   entry defining_identifier
         [(discrete_subtype_definition)] parameter_profile;

The entry declaration must be placed inside the task specification. The parameter profile is the same for Ada procedures (in, out and in out -- with in being the default). Access parameters are not permitted, though parameters of any access type are, of course, allowed. Default parameters are also allowed. The optional Discrete_Subtype_Definition in the entry declaration is used to declare a family of entries (an array of entries), all of which will have the same formal part. Similar to procedures, entries can be overloaded. This means that a task can have more than one entry with the same name if the parameters to the entries are different [BW98, section 5.2].

Simple Mode Entry Call

A client task (also referred to as calling task) issues an ``entry call'' on the server task by identifying both the server and the required entry [BW98, section 5.1].

  entry_call_statement ::= entry_name [actual_parameter_part];

As the reader can see, a simple mode entry call is much like a procedure call. It may have parameters, which permit values to be passed in both directions between the calling and accepting tasks. Semantically the calling task is blocked until completion of the requested rendezvous. If the call is completed normally, it resumes execution with the statement following the call, just as it would after return from a procedure call. Recovery from any exception raised by the call is also treated as it would be for a procedure call. One minor difference detectable by the calling task is that an entry call may result in Tasking_Error being raised in the calling task, whereas an ordinary procedure call would not [BR85, Section 6].

Conditional Entry Calls

The conditional entry call allows the task client to withdraw the offer to communicate if the server task is not prepared to accept the call immediately [BW98, section 6.9.2]. The syntax is [AAR95, section 9.7.3]:

   conditional_entry_call ::=
      end select;

   entry_call_alternative ::=
      entry_call_statement [sequence_of_statements]

Accept Statement

The server task indicates a willingness to provide the service at any particular time by executing an ``accept'' statement [BW98, section 5.1]. The syntax is [AAR95, section 9.5.2]:

 accept_statement ::=
    accept entry_direct_name [(entry_index)] parameter_profile [do
    end [entry_identifier]];

The accept statement specifies the actions to be performed when the entry is called. It must be placed in the task body; it can not be placed in a procedure which is called by the task body [BW98, section 5.3]. For the communication to occur between the client and the server, both tasks must have issued their respective requests. When they have, the communication takes place; this is called the rendezvous because both tasks have to meet at the entry at the same time. When the rendezvous occurs, any in (and in out) parameters are passed to the server task from the client. The server task then executes the code inside the accept statement. When this statement finishes, out (and in out) parameters are passed back to the client and both tasks proceed independently and concurrently [BW98, section 5.1].

It is quite possible that the client and server will not both be in a position to communicate at exactly the same time. For example, the operator may be willing to accept a service request but there may be no subscribers issuing an entry call. For the simple rendezvous case, the server must wait for a call; whilst it is waiting it frees up any processing resource it is using; a task which is generally waiting for some event to occur is usually termed suspended or blocked. If a client issues a request and the server is not ready to accept the request (either because it is already servicing another request or it is doing something else), then the client must wait. Clients waiting for service at a particular entry are queued. The order of the queue depends on whether the Ada implementation supports the Real-Time Systems Annex [AAR95, Annex D]. If the annex is not supported, then the queue is first-in-first-out; otherwise other possibilities are allowed including priority queuing [BW98, section 5.1].

If an exception is raised during the rendezvous, then the rendezvous is terminated and the exception is raised again in both the server (called) and the client (calling) task. In addition, when a task attempts to call another task that has already terminated (completed or has become abnormal), the caller task gets the exception Tasking_Error raised at the point of the call [BW98, section 5.7].

Selective Accept

The ``selective accept'' allows a server task to [BW98, section 6.1]:

The syntax of the selective accept is [AAR95, section 9.7.1]:

   selective_accept ::=
   { or
        select_alternative }
   [ else
       sequence_of_statements ]
     end select;

   guard ::= when condition =>

   select_alternative ::=
      | delay_alternative
      | terminate_alternative

   accept_alternative ::=
      accept_statement [sequence_of_statements]

   delay_alternative ::=
      delay_statement [sequence_of_statements]

   terminate_alternative ::= terminate;

A selective accept must contain at least one accept alternative. It is possible that several clients may be waiting on one or more of the entries when the server task executes the select statement. In this case, the one chosen is implementation dependent. This means that the language itself does not define the order in which the requests are serviced. If the implementation is supporting the Real-Time Systems Annex [AAR95, section D], then certain orderings can be defined by the programmer. For general-purpose concurrent-programming, the programmer should assume that the order is arbitrary; that way the program cannot make any assumptions about the implementation of the language and thus it will be portable across different implementation approaches. By default, single queues are serviced on a first-come first-served basis [BW98, section 6.1].

Each selective accept alternative can have a guard associated with it. This guard is a boolean expression which is evaluated when the select statement is executed. If the expression evaluates to True, the alternative is eligible for selection. If it is False, then the alternative is not eligible for selection during this execution of the select statement, even if clients are waiting on the associated entry. It is an error if a selective accept statement has a guard on each of its alternatives and all the guards evaluate to False. When this happens, the exception Program_Error is raised. Alternatives without guards are deemed to have ``true'' guards [BW98, section 6.2].

The else part allows the server to withdraw its offer to communicate if no call is immediately available. The else part can not be guarded and consequently only one else part may appear in a single select statement [BW98, section 6.4].

The delay alternative of the selective accept allows a server task to time-out if an entry call is not received within a certain period of time. The time-out can be a relative or an absolute delay. If the relative time expressed is zero or negative, or the absolute time has passed, then the delay alternative is equivalent to having an ``else part''. More than one delay alternative is allowed, though only the delay with the smallest time interval will act as the time-out. Relative and absolute delay alternatives can not be mixed in a single select statement [BW98, section 6.3]. Timed sentences will be analyzed in chapter [*].

The terminate alternative allows a server task to become completed when the following conditions are satisfied [BW98, section 6.6]:

When both the above conditions are satisfied, not only is the server task completed but so also are all tasks that depend on the master being considered. Once these tasks are completed any associated finalization code is executed [BW98, section 6.6].

The Count Attribute

Each entry queue has an attribute associate with it that allows the current length of the queue to be accessible to the owning task. E'Count returns a natural number representing the number of entry calls currently on the entry E, where E is either a single entry or a single entry of a family [BW98, section 5.3.1]. The Count attribute can only be used within the body of the task but not within a dependent subprogram.

next up previous contents index
Next: GNAT Implementation Up: The Rendezvous Previous: The Rendezvous   Contents   Index
(c) Javier Miranda. Canary Islands (Spain), 2002. Version 1.0