Section 13.1 - Tasking Basics
The Ada language includes built-in support for concurrent (parallel)
processing with Ada tasks.
Ada tasks run concurrently and can interact with each other using a few
different mechanisms.
In essence, each Ada task works as though it were running on
a separate computer.
Tasks are called by some people ``threads'' or ``light-weight processes''.
More general terms for task-like behavior include ``process'',
``agent'', and ``active object''.
Why would you want to use tasks?
Well, here's one example - let's imagine you're developing a
World Wide Web browser.
Such a browser must download information through some (slow) communication
device and then display the information.
Now, you could wait until all the information was available and then
display it, but that would make the user wait for a possibly long time.
A better solution would be to have two tasks - one that downloads the
information, and another that displays the information.
As the first task gathers more information, it could pass portions of
what it's downloaded along to the second task.
The second task could work to display information to the user, even if
the first task hasn't finished gathering its data yet.
Both tasks could then work ``simultaneously''.
Tasks can be started up (activated) and stopped (terminated).
There are a variety of ways tasks can communicate with each other
once they are activated; the main ways are:
-
Tasks can wait for other tasks to complete.
-
Tasks can send messages between each other; this is called a
rendezvous.
-
Tasks can use `protected objects', which provide exclusive read-write access
to data.
Protected objects are new to Ada 95.
-
Tasks can set global variables to communicate.
This last method is efficient but dangerous, especially if you do not
have a thorough understanding of concurrency issues.
Ada permits this last approach because some real-time system developers
really want this capability, but use this approach with great caution.
We'll discuss these different communication methods in the next few sections.
Some computing systems actually have several computers built into them.
If the Ada compiler and/or operating system can do so, different tasks
may be run on different machines, which may significantly speed up
execution of a program.
There are some important caveats about tasks:
-
Ada can't create what doesn't exist.
On single-CPU machines, Ada must simulate
multiple computers on a single computer, and there
is some overhead to doing that.
This overhead is called the ``scheduling overhead,''
and a significant portion of the scheduling overhead is something called the
``context switching time''.
Most compiler vendors provide information about these values.
-
Tasks can be under-used or over-used.
Some people create hundreds of unnecessary tasks,
producing slow, terrible programs.
Like any other tool, use tasks appropriately.
As a rule of thumb, check what you're doing if you're using more
than ten to twenty tasks on a single CPU, especially if more than a
few of them are simultaneously active.
Also, while there may be many low-level (hardware-level) tasks that
do trivial work, tasks should generally not simply
do a trivial operation and then send information on to yet another task.
Do not follow these rules slavishly; think of these as naive
guidelines until you understand tasking more completely.
-
If there's an underlying operating system, the operating system
must provide some reasonable support for Ada tasks to work well.
Modern operating systems that support threads or light-weight
processes generally work nicely; such
operating systems include Windows NT, Windows 95, OS/2, Mach, and Solaris.
Nearly all real-time operating systems provide mechanisms sufficient for
implementing Ada tasks.
Windows 3.1 and some old Unix systems do not provide such support, and
this causes some minor but annoying limitations on those
systems as we'll discuss later.
MS-DOS doesn't directly support threads, but it's such a primitive operating
system that tasks can be created by simply taking over the entire machine
(old versions of GNAT didn't support tasking on MS-DOS; that has since been
added by specially implementing tasks on top of MS-DOS).
Technically speaking, an Ada program always includes at least one
task, called the environment task; the main (starting) subprogram
runs in this environment task.
Quiz:
Software XYZ is running on a single processor and has
10,000 tasks.
There's a task for every switch on an input panel
and a task for every light on a display panel.
Does this sound like a good design?
- This is probably a good design.
- This is probably not a good design.
You may also:
David A. Wheeler (dwheeler@ida.org)