next up previous contents index
Weiter: 19.3.2 Transporter-Tasks Hinauf: 19.3 Die Realisierung Zurück: 19.3 Die Realisierung

 

19.3.1 Buffer-Tasks

 

Ein Buffer-Task wird sowohl vom Producer-Task als auch vom Consumer-Task aufgerufen und dient als Zwischenspeicher von Datenelementen (siehe Abb. 19.7).

 
Abbildung 19.7: Buffer-Task 

Eine Realisierung durch ein generisches Paket könnte folgendermaßen aussehen:

generic
size: in natural := 20;
type item is private;
package Generic_Buffer is
procedure Enqueue (I: in item);
procedure Dequeue (I: out item);
end Generic_Buffer;

package body Generic_Buffer is
task Buffer is
entry Enqueue (I: in item);
entry Dequeue (I: out item);
end Buffer;

task body Buffer is separate;

procedure Enqueue (I: in item) is
begin
Buffer.Enqueue (I);
end Enqueue;

procedure Dequeue (I: out item) is
begin
Buffer.Dequeue (I);
end Dequeue;
end Generic_Buffer;

Die aufgeschobene Implementation des Task-Body's von Buffer könnte so realisiert werden:

separate (Generic_Buffer)

task body Buffer is
subtype Index_Type is positive range 1 .. size;
subtype Count_Type is natural range 0 .. size;

Buf: array (Index_Type) of Item;
Insert: Index_Type := 1;
Remove: Index_Type := 1;
Count: Count_Type := 0;
begin
loop
select
when Count < size =>
accept Enqueue (I: in item) do
Buf(Insert) := I;
end Enqueue;
Insert := (Insert mod Buf'LAST) + 1;
Count := Count + 1;
or
when Count > 0 =>
accept Dequeue (I: out item) do
I := Buf(Remove);
end Dequeue;
Remove := (Remove mod Buf'LAST) + 1;
Count := Count - 1;
or
terminate;
end select;
end loop;
end Buffer;

Da in diesem Fall der Buffer-Task nicht nur passiv ist, sondern auch keinerlei lokale Aktivitäten setzt, kann er auch als geschütztes Objekt realisiert werden. Die Spezifikation des generischen Paketes bleibt natürlich dieselbe, der Implementationsteil sieht dann allerdings folgendermaßen aus:


package body Generic_Buffer is

subtype Index_Type is positive range 1 .. size;
subtype Count_Type is positive range 0 .. size;
type item_array is array (Index_Type) of Item;

protected Buffer is
entry Enqueue (I: in item);
entry Dequeue (I: out item);
private
Buf: item_array;
Insert: Index_Type := 1;
Remove: Index_Type := 1;
Count: Count_Type := 0;
end Buffer;

protected body Buffer is separate;

procedure Enqueue (I: in item) is
begin
Buffer.Enqueue (I);
end Enqueue;

procedure Dequeue (I: out item) is
begin
Buffer.Dequeue (I);
end Dequeue;
end Generic_Buffer;

Die aufgeschobene Implementation des Body's des geschützten Buffers lautet:


separate(Generic_Buffer)

protected body Buffer is
entry Enqueue (I: in item) when Count < size is
begin
Buf(Insert) := I;
Insert := (Insert mod Buf'LAST) + 1;
Count := Count + 1;
end Enqueue;
entry Dequeue (I: out item) when Count > 0 is
begin
I := Buf(Remove);
Remove := (Remove mod Buf'LAST) + 1;
Count := Count - 1;
end Dequeue;
end Buffer;



next up previous contents index
Weiter: 19.3.2 Transporter-Tasks Hinauf: 19.3 Die Realisierung Zurück: 19.3 Die Realisierung

Johann Blieberger
Wed Feb 11 09:58:52 MET 1998