Document Sample
Project2 Powered By Docstoc
					CS 472                          Programming Project 2                                     Due date:
Spring 2010                           50 Points                                            March 18

This project delves deeper into Ada multitasking and involves use of the select statement, arrays of
tasks, and a parameterized task type. It identifies and outputs all the prime numbers up to 1000 by a
method related to the Sieve of Eratosthenes. There will be a total of 23 tasks in addition to the
main procedure.

You are given a partially written Ada program named Primes in file Primes.adb (as attached to the
end of this document; download a copy of this file from the class web site). Observe that this
concurrent program includes two task types: FilterType and BufferType. Your job is to write the
activity of the main procedure and the bodies of the two task types.

The basic idea for identifying prime numbers is the observation that a test integer N is prime if it is
not evenly divisible by any prime number in the range from 2 to N . The largest integer smaller
than 1000 is 31, which happens to be the 11th prime number. Therefore we will need to divide
each test integer in the range 2 to 1000 by no more than 11 primes to determine if it is prime.
Except for the prime 2, identification of the first 11 primes is to be done dynamically by the

The main procedure has an array of 11 FilterType tasks named Filter. Each FilterType task is
initialized to one of the first 11 primes, say prime p. It is then provided with a sequence of test
integers and is responsible for “filtering out” those that are divisible by the prime p. If a test integer
is not eliminated, the task passes it along to the next filter task to be checked for divisibility by the
next prime. If the test integer passes through all the filters, it is identified as a prime number.

For efficiency, there is a second array of 11 BufferType tasks named Buffer. Each BufferType task
represents a queue ADT of integers with a capacity established by a task-type parameter when it is
declared (the declaration is provided for you and uses a parameter value of 5). The purpose of each
buffer task is to buffer integers being sent from one filter task to the next filter. Altogether, the
array of buffers reduces the amount of task switching due to data not being available.

Each buffer has entries Enqueue, Dequeue, and Size, which correspond to the standard queue
operations. A select statement should be used to allow calls to these entries to be accepted in any
order. The data of the queue should be stored in local variables of the task. The first thing a buffer
task should do when it starts running is output the message: “Buffer task started . . .” on a single
line; the last job for each buffer is to output “Buffer task terminates” on a single line.

The buffer Primes declared in the main procedure is intended to store all primes in the order in
which they are discovered. It is an “output buffer” with a capacity of 200.

The activity of the main procedure initializes the first task in Filter(1) so that it will check for
integers divisible by the prime 2 and then Enqueues prime 2 in output buffer Primes. It then
Enqueues integers 3 through 1000 in Buffer(1). Finally, it Enqueues integer 0 in Buffer(1) to act as
sentinel to be used for termination. After checking that all test integers have been evaluated by the
filters and all primes have been placed in the output buffer Primes (it is your job to figure out a
way to do this – you are allowed to add a task entry somewhere if needed), the main procedure
should output all primes in the output buffer to the screen. The output should be according to the

A table of primes follows:
      pos prime
      --- -----
        1    2
        2    3
        3    5
        4    7
        5   11
        6   13
        7   17
        8   19
        9   23
       10   29
       11   31
       12   37
       ...    ...

        End of table

The Initialize entry of each filter task (used for initialization) involves two parameters: Position and
Divisor. Position tells the task its position in the array, which it needs to know when it works with
the neighboring buffers. The Divisor parameter is the prime number that the task will use when
dividing test integers.

After accepting a call to initialize, a filter task should output “Filter task number <n> initialized for
the prime <p>” on a single line (replace <n> and <p> by the appropriate values). It should then get
test integers from the appropriate buffer and test them. When a filter task first finds a test integer
that is not evenly divisible by Divisor, this test integer is prime. In this case, it should Enqueue the
new prime in the output buffer, Primes, and Initialize the next filter task for the new prime. Integers
that are evenly divisible should be discarded. When subsequent test integers are not evenly
divisible, they might prime and should be passed on to the next buffer. Note: The last filter task
Filter(11) should behave differently from the others since there is no “next” filter; instead, it should
direct all test integers that are not eliminated to the output buffer. Finally, after being passed the
sentinel 0, each filter task should forward the 0 to the next filter (except the last) and output “Filter
task number <n> terminating” on a single line.


1. Disk with your default folder Project2 at the root. This folder should contain an executable file
   named Primes.exe and a project file named Project2.gpr.
2. Hard copy of a listing of your complete implementation of Primes.adb.
3. Hard copy of output.
with Ada.Text_IO;
procedure Primes is
  MaxTasks : constant Integer := 11;
  package Int_IO is new Ada.Text_IO.Integer_IO( Integer );
  task type FilterType is
     entry Initialize( Position : Integer; Divisor : Integer );
  end FilterType;
  task type BufferType( Capacity : Positive ) is
     entry Enqueue( N : in Integer );
     entry Dequeue( N : out Integer );
     entry Size( S : out Integer );
  end BufferType;
  -- Local variables for main procedure
  Filter : array( 1..MaxTasks ) of FilterType;
  Buffer : array( 1..MaxTasks ) of BufferType( 5 );
  Primes : BufferType( 200 );
  <Replace this by local variables for the main procedure and by the two task bodies>
begin – Primes
  <Replace this by activity of the main procedure>
end Primes;

Shared By: