home *** CD-ROM | disk | FTP | other *** search
-
-
-
- Chapter 27
- ADDITIONAL TASKING TOPICS
-
-
- We have covered most of the topics concerning tasking in the last
- three chapters, but there are a few more tasking themes that must
- be considered in order for you to use tasking to the fullest. The
- topics in this chapter are definitely advanced tasking topics and
- you may wish to ignore some of this material until you have gained
- considerable experience in the use of Ada. It would be worth your
- time to at least read through this material once to gain some
- exposure to it and to realize that these capabilities exist in the
- Ada programming language.
-
-
- THE TASK TYPE
- _________________________________________________________________
-
- Examine the program named TASKTYPE.ADA for an ================
- example of the task type in Ada. This will seem TASKTYPE.ADA
- like a very strange construct, but if you spend ================
- time thinking about it, you will see that it
- does have a place in an Ada program, and it can
- be very useful.
-
- In all previous programs with tasking, we have declared a task
- specification followed by a task body, but that is not the general
- case. It is actually a shorthand notation for declaring tasking
- and is somewhat similar to an anonymous type. The more general
- case of task definition is to declare a task type specification,
- then the task body, followed by a task that is of the declared
- type. In fact, the task is declared in much the same way we have
- been declaring variables in Ada, the task name followed by a colon
- and the task type. In the present program we declare the first
- task type specification in lines 7 and 8, and the corresponding
- task body in lines 16 through 22. The task itself is declared in
- line 13 where Cow is declared to be of task type SHORT_LINE. In
- fact, there are three tasks declared in this line, the other two
- being named Dog and Pig.
-
-
- WHAT DOES IT REALLY MEAN?
- _________________________________________________________________
-
- If we declared a data type, then used the data type to declare
- three variables, you would have no trouble understanding what was
- happening, because you have been doing that all along in this
- tutorial. It may be a little more difficult for you to understand,
- but we are doing the same thing with the task, except that we are
- declaring a type of a section of code, then generating and
- executing three copies of that code. It is the same as if we
- declared a task specification named Cow that was identical to that
- given in lines 7 and 8, then a task body named Cow that was
-
- Page 27-1
-
- Chapter 27 - Additional Tasking Topics
-
- identical to that given in lines 16 through 22, and did exactly the
- same thing for the other two tasks named Dog and Pig. Instead of
- duplicating the code three times we declared a pattern for the task
- then told the system to run three copies of it.
-
- The task itself is extremely simple, consisting of a loop with a
- zero delay, and a statement to output a message to the standard
- output device, the monitor. The tasks themselves are declared in
- line 13 before the task body is declared, but this should pose no
- difficulty for you since we have used partial declaration of
- subprograms and types before. You will recall that Ada is designed
- such that "small" declarations must all be declared before any
- subprogram or package bodies to keep the smaller entities near the
- beginning. It would therefore be a compile error to move the task
- declarations given in line 13 after the task body declarations.
-
- A fine point should be mentioned here. A task type is always of
- limited private type, which means you can do no operations on it.
- Assignment and comparisons are not available with a limited private
- type, and it makes sense to prevent these operations with tasks.
-
-
- THERE ARE TWO TASK TYPES DECLARED
- _________________________________________________________________
-
- In addition to the task type named SHORT_LINE, there is another
- named LONG_LINE similar to the first, which outputs only three
- lines until it completes, but outputs a much longer line of text.
- Two copies of this type are declared and executed.
-
- The end result of all of this is the generation and execution of
- five tasks all running in parallel with no rendezvous between them
- except for the zero time delay statements as discussed in an
- earlier chapter.
-
-
-
- WHEN DO THEY RUN?
- _________________________________________________________________
-
- We discussed in an earlier chapter how each of the tasks got
- started running and this is no different. When all five tasks have
- been completely elaborated and are all waiting at their respective
- begin statements, and when the main program arrives at its begin
- statement, then all of the tasks begin to execute. Remember that
- there are six tasks counting the main program as a task. Likewise,
- when all of the tasks, including the main program, reach their end
- points, an orderly termination is effected and the program ceases
- to execute, returning control to the operating system.
-
- Compile and run this program and you will see that all five tasks
- do indeed run as described above. Add a few additional tasks in
- lines 13 and 14 to see how easy it is to add additional tasks once
- the task type is completed. It would be well worth your time to
-
- Page 27-2
-
- Chapter 27 - Additional Tasking Topics
-
- study this program until you understand this material, because it
- will be used in the next few example programs.
-
-
- A TASK AS PART OF A RECORD
- _________________________________________________________________
-
- It will not be illustrated here, but it is possible to declare a
- task type variable as part of a record. Such a record can be used
- to declare a task variable along with a few other variables for use
- by the task.
-
-
- AN ARRAY OF TASKS
- _________________________________________________________________
-
- Examine the program named TASKARRY.ADA for an ================
- example of an array of task types. This program TASKARRY.ADA
- is identical to the last except for the addition ================
- of an array of tasks in line 13. The task name
- Cow is declared to be an array of tasks named
- Cow(1), Cow(2), ... Cow(4), so there are four tasks of this type
- running concurrently when execution begins. These four are in
- addition to the two of type LONG_LINE as in the previous program.
- Nothing more needs to be said about this program except for you to
- compile and execute it to see that you really do get all six tasks
- running in parallel with the task in the main program. There are
- actually seven tasks running in parallel. It would be a snap to
- increase the Cow array to 6 tasks and see nine running, the six in
- the array, the two which are the other type, and the main program.
-
-
-
- A TASK ACCESS TYPE
- _________________________________________________________________
-
- Examine the program named TASKACES.ADA for an ================
- example of an access type which can be used to TASKACES.ADA
- access a task. Once we have the ability to ================
- access a task through an access variable, we can
- also dynamically allocate a task and execute it.
- We will illustrate this operation in the present example program.
-
- This program in nearly identical to the last two except that the
- variables named Elephant and Hippopotamus are not task type
- variables, but task access type variables because we declared the
- type LONG_POINT as an access variable in line thirteen.
-
- When we execute this program, the three statically declared tasks
- begin executing when the main program does, but the two access type
- variables do nothing because they are simply access types that
- access nothing yet. The main program outputs a line of text to the
- monitor, then dynamically allocates a copy of the task type
- LONG_LINE in line 37 and the new task begins executing. Another
-
- Page 27-3
-
- Chapter 27 - Additional Tasking Topics
-
- task is allocated and begins execution in line 38. All five tasks
- will run to completion and there will be an orderly termination.
-
- In this case, the main program is a parent task to the two
- dynamically allocated tasks and they are referred to as children
- tasks of the main program.
-
-
- WHEN DO THEY BEGIN EXECUTION?
- _________________________________________________________________
-
- The biggest difference between this program and the previous two,
- involves when the respective tasks begin execution. All of the
- statically declared tasks begin execution when the main program
- begins, but the dynamically allocated tasks begin execution when
- they are allocated. This can be clearly seen by studying the
- result of execution of each of the three programs. In the present
- program, the first output of each of the two allocated tasks is
- delayed considerably behind the first output of the statically
- declared tasks.
-
- Be sure to compile and execute this program and compare the output
- of your compiler with that generated by the author's Ada compiler.
- It would be a simple matter for you to add a few more access
- variables and allocate additional tasks just to gain the
- experience.
-
-
- A VERY INEFFICIENT EXAMPLE OF TASKING
- _________________________________________________________________
-
- The example program named PARALLEL.ADA is an ================
- example of a very poor way to solve this PARALLEL.ADA
- particular problem but is a meaningful example ================
- of a tasking solution to a problem. In this
- program we will declare eleven parallel tasks,
- start all eleven running, then retrieve the results of the eleven
- tasks.
-
- We begin by declaring several types and variables, then declare a
- task specification in lines 20 through 23 with two entry points.
- Because the constant EMPLOYEES is declared as having the value 11,
- we declare 11 tasks in line 25, named Adding_Task(1),
- Adding_Task(2), ... Adding_Task(11), each of which will begin
- running when we begin execution of the main program. The task
- body, given in lines 28 through 42, consists of a local variable,
- and two accept statements, with a few calculations between them.
-
- The main program is the most interesting part of this program, but
- we need to get through the initialization code before we come to
- the interesting part. The initialization code in lines 45 through
- 51, assigns values to the big array declared previously including
- a couple of funny data points which will show up in the results.
- Finally, we display a message that the array is filled.
-
- Page 27-4
-
- Chapter 27 - Additional Tasking Topics
-
-
- START ALL TASKS RUNNING
- _________________________________________________________________
-
- The loop in lines 56 through 58 calls the eleven tasks at their
- first entry point and begins them executing so that they all are
- executing their respective for loops. If you had a computer with
- a large number of actual processors, each task could be assigned
- to a separate processor and all calculations could be done
- concurrently. In the present case of adding seven numbers, the
- calculations are trivial, but if each task required the performance
- of several million floating point operations, the time saved
- through the efficient use of parallel hardware could be very
- significant. This program serves to illustrate the technique that
- could be used and is the most practical illustration of tasking to
- be demonstrated in this course.
-
-
- ALL TASKS ARE NOW COMPLETE
- _________________________________________________________________
-
- The loop in lines 61 through 64 once again calls all eleven tasks
- one at a time at their final entry point where it requests that the
- result of the summation be returned. All results are stored in the
- Weekly_Totals array, and the results are then displayed along with
- appropriate text. You will notice, when you examine the result of
- execution, that employees numbered 2 and 3 have the funny data
- reflected in their totals.
-
- The point of interest you should have gleaned from this program is
- that all eleven tasks were operating in parallel, with the main
- program being a twelfth task. The logic of the main program
- requires concurrent tasks as opposed to eleven calls to a single
- subprogram. Keep in mind that this would actually be a very poor
- way to program this particular problem.
-
- Be sure to compile and execute this program on your system to
- verify that the results are the same. After it does compile and
- execute correctly, change the number of employees to see how many
- tasks can be operated in parallel with your system. You will
- probably not be limited by some arbitrary upper limit on the number
- of allowable tasks, imposed by your particular compiler, but by the
- amount of memory required for each task.
-
-
- PRIORITY OF TASKS
- _________________________________________________________________
-
- The example program named PRIORITY.ADA contains ================
- an example of establishing priority within PRIORITY.ADA
- tasks. The priority of tasks is indicated by ================
- the use of the pragma named PRIORITY as
- illustrated in the task specifications and the
- declaration part of the main program. An integer class variable
-
- Page 27-5
-
- Chapter 27 - Additional Tasking Topics
-
- is included in the parentheses with the larger numbers indicating
- the higher priority or the most urgent tasks. The range of
- allowable priorities are defined for your individual compiler in
- the System specification package definition as a subrange of
- INTEGER. According to the LRM, a range of 0..0 is legal. If your
- compiler only supports a single value for the priority, you will
- have to change the priorities in this program to the single value
- and you will, in effect, have no priority.
-
- Compile and execute this program, then change the priorities and
- see what order of execution you can achieve. It is important to
- realize that the LRM does not absolutely define how priorities will
- be handled, but it only gives a rather vague definition.
- Priorities should be used with care in a production program.
-
-
- A FAMILY OF ENTRIES
- _________________________________________________________________
-
- The example program named FAMILY.ADA illustrates ================
- one more construct that can be used with the FAMILY.ADA
- tasking rendezvous to achieve a user defined ================
- priority structure. In this case, there are
- three entry points which are very similar but
- have only a small difference between them. An enumerated variable
- is declared and used as the discriminator between the three
- entries. The only real advantage to using a family of entries is
- that they all use the same name and therefore add to the clarity
- of the resulting program.
-
- The use of the family of entries is illustrated here and should be
- very easy for you to understand. When you do, compile and execute
- this program and compare your output with that given in the result
- of execution section.
-
-
- PROGRAMMING EXERCISES
- _________________________________________________________________
-
- 1. Increase the size of the array in TASKARRY.ADA to see how big
- you can make this array before the program no longer fits in
- memory. This will give you an idea of how many tasks can be
- run at the same time with your system.
-
- 2. Add another access variable to TASKACES.ADA and initialize it
- as a part of its declaration. When will this task begin
- execution?
-
-
-
-
-
- Page 27-6