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.