11.Tasks
In Ada, Tasks are entities whose executions proceed in parallel.
Different tasks ( different logical processors ) proceed independently,
except at points where they synchronize. Some tasks may have entries.
An entry of a task can be called by other tasks. A task accepts a call of
one of its entries by executing an accept statement for the entry.
Synchronization is achieved by "rendezvous mechanism" between a task
issuing an entry call and a task accepting the call. A task unit consists of
a task specification and a task body.
Ada Tasking can be applied for providing protection to any applications,
not only for real-time applications. Protection mechanism is an essential
issue in computer science applications. [Tracz 90] argues that the
traditional way of designing packages has the following limitations.
* interfaces have side effects
* implementations doesn't retain the state between invocations.
* it is useful only for concurrent programming situations, where
multiple processes are competing for resources.
[Gautier, Wallis 90] discusses the same issue for providing protection
mechanisms and its situations. Here is an integrated approach to solve
such problems. It is illustrated with a package for queued elements
using stack operation. It provides two kinds of Stack implementations.
One, a finite stack for use with sequential programs, and second one for
use with multi-tasking programs. Each instantiation of the package
requires a type parameter that specifies the type of the queued
elements. After instantiation, any number of queues may be declared
by using the types Stack and Blocking-Stack.
generic
type Item is private;
type Stack_Size is range (<>);
package Stack_Abstraction is
type Stack ( Max_size : Stack_size ) is limited private;
procedure Push( Elem : in Item; St : in out Stack );
procedure Pop ( Elem : in Item; St : in out Stack );
function Is_empty ( St : in Stack ) return Boolean;
function Is_Full ( St : in Stack ) return Boolean;
procedure Init_stack ( St : in out Stack );
procedure Destroy_stack ( St : in out Stack );
Overflow, Underflow : exception;
type Blocking_Stack ( Max_stack : Stack_Size) is limited
private;
procedure Push ( Elem : in Item; St : in out Blocking_Stack );
procedure Pop ( Elem : in Item; St : in out Blocking_Stack );
function Is_empty ( St : in Blocking_Stack ) return Boolean;
function Is_Full ( St : in Blocking_Stack ) return Boolean;
procedure Init_stack ( St : in out Blocking_Stack );
procedure Destroy_stack ( St : in out Blocking_Stack );
pragma Inline ( Is_empty, Is_full, Init_stack, Destroy_stack
);
private
type Stack ( Max_Size : Stack_size ) is
record
-----------------------------------
task type Blocking_Stack_Task is
entry Pass_Discriminants ( Blocking_stack_size :
stack_size );
entry Put_Item ( Elem : in Item );
entry Get_Item ( Elem : in Item );
entry Check_Full ( B : out Boolean );
entry Check_empty ( B : out Boolean );
entry Shutdown;
end Blocking_Stack_Task;
type Blocking_Stack ( max_size : stack_size ) is
record
Monitor : Blocking_Stack_Task;
end record;
end Stack_Abstraction;
Guideline1 : Define task types instead of single tasks so that it
promotes abstractions for reuse.
Guideline2 : Define tasks and task types in the package body so that it
hides detailed implementations.
Guideline3 : Define access type to designate task objects which allows
dynamic creation of task objects as shown below.
type Blocking_stack_linker is access Blocking_Stack_Task;
Blocking_stacks : Blocking_stack_linker := new
Blocking_Stack_Task;
Guideline4 : For every entry procedure, there should be an accept
statement in Ada tasking.
Guideline5 :In task body, terminate statement should be used as final
alternative of a select statement in order to ensure that the task doesn't
wait indefinitely as shown in the following example.
task body Buffer_task is
------------
loop
select
--- conditional accept statement ----
when not empty =>
accept Read_Buffer;
or
accept Write_Buffer;
or
accept Finish;
exit;
or
terminate;
end select;
end loop;
end Buffer_task;
Guideline6 : Always design conditional accept statement using when
statement within select construct in the body of Ada tasking.