Previous | Next | Table of Contents | Index | Program List | Copyright

Chapter Review

In this chapter we introduced Ada tasks and protected types. These are used to support concurrent programming, which is the writing of programs with multiple threads of control or processes.

Tasks are active program units that act as processes; in a given program, each task is separately activated and executes independently of the others. A task is an interesting kind of program unit: It has a specification and a body like a package, contains a declaration section and a sequence of statements like a procedure, and has a type like a data structure. Tasks are declared like other variables; they can also be array elements. We have seen a few examples of task discriminants and entries; other tasking statements, especially the SELECT statement, are very interesting but beyond the scope of our discussion here.

A protected type is a way to create an encapsulated data structure with operations that are protected in a concurrent environment. Protected operations can be functions, procedures, or entries; in this brief presentation we have introduced only procedures. The Ada 95 standard provides that multiple concurrent calls of a protected procedure are fully executed one at a time, preventing the multiple calls from interfering with each other and modifying the data structure unpredictably.

We have hardly begun to explore the richness of concurrent programs in Ada; we hope this brief introduction has sparked your interest in the subject and that you will continue to learn more about concurrent programming in general and its Ada implementation in particular.

New Ada Constructs in Chapter 16

The new Ada constructs introduced in this chapter are described in Table 16.1.

Table 16.1
Summary of New Ada Constructs

Construct					Effect
Task Type
TASK TYPE SimpleTask				SimpleTask is a type; Message and 
           (Message: Character;			HowMany are discriminants whose
            HowMany: Positive) IS		values are passed to the task
  ENTRY StartRunning;				objects when they are activated.
END SimpleTask;					StartRunning is a "start button" 
						entry.
TASK BODY SimpleTask IS
BEGIN -- SimpleTask
  ACCEPT StartRunning;				Each task object waits here for its
						entry to be called, and then 
  FOR Count IN 1..HowMany LOOP			continues on its own.
    Ada.Text_IO.Put
      (Item => "Hello from Task " & Message);
    Ada.Text_IO.New_Line;
    DELAY 0.1;
  END LOOP;
END SimpleTask;
Task Object
Task_A: SimpleTask
          (Message => 'A', HowMany => 5);	Two task objects are declared
Task_B: SimpleTask				with discriminant values
          (Message => 'B', HowMany => 7);
Entry Call
Task_B.StartRunning;				The two tasks' "start button"
Task_A.StartRunning;				entries are called.
Protected Type
PROTECTED TYPE ScreenManagerType IS		ScreenManagerType provides a
  PROCEDURE Write (Item:   IN String;		protected procedure Write.
                   Row:    IN Screen.Depth; 	Multiple calls to Write are
                   Column: IN Screen.Width);	guaranteed to be processed one
PRIVATE						at a time. This provides mutual
  -- a data structure could be declared here	exclusion on operations that 
END ScreenManagerType;				modify the protected structure.

PROTECTED BODY ScreenManagerType IS
  PROCEDURE Write (Item:   IN String; 
                   Row:    IN Screen.Depth; 
                   Column: IN Screen.Width) IS
  BEGIN -- Write
    Screen.MoveCursor
      (Row => Row, Column => Column);
    Ada.Text_IO.Put(Item => Item);
  END Write;
END ScreenManagerType;
Protected Object
Manager: ScreenManagerType;			Manager is a protected object.

Quick-Check Exercises

  1. How is a task different from a procedure?
  2. When are tasks activated? What is the order of activation?
  3. If multiple tasks are active, how do they share the CPU?
  4. How does a task handle an ACCEPT in its task body?
  5. What happens when a task calls an entry in another task?
  6. How does a protected procedure differ from an ordinary procedure?

Answers to Quick-Check Exercises

  1. A procedure is called, but a task is activated implicitly and has its own thread of control.
  2. Tasks are activated just after the BEGIN of the block in which they are declared. Ada does not predefine an order of activation.
  3. The run-time system may or may not time-slice the tasks; if it does not, the first task to get the CPU will keep it until that task reaches a DELAY or other statement that causes it to block.
  4. The task waits at the ACCEPT until another task calls the entry.
  5. It waits at the point of call until the called task accepts the call at an ACCEPT statement.
  6. An ordinary procedure can be called simultaneously by several tasks. Multiple calls of a protected procedure are executed one at a time.

Review Questions for Chapter 16

  1. Explain, in as much detail as you can provide, how multiple tasks can share a single computer.
  2. Explain why protected types are necessary.

Programming Projects

  1. Investigate whether your Ada implementation supports time-slicing, and if it does, whether time-slicing can be turned on and off at will. Experiment with doing so, using Program 16.2 as a test program.
  2. Experiment with using different starting orders in Program 16.4. Is there any difference in the behavior?
  3. Section 16.4 suggests a modification to the body of the Spiders package (Program 7.11, modified according to the specification in Program 10.19) using a protected type to keep track of the spiders on the board. Modify the package accordingly and test it using Program 6.8 or 6.9. Now remove the protection from the Move procedure, that is, declare it as an ordinary procedure and the board as an ordinary data structure. Test again; is there any difference in the behavior?


Previous | Next | Table of Contents | Index | Program List | Copyright

Copyright © 1996 by Addison-Wesley Publishing Company, Inc.