The following Ada code is a simple simulation of a just in time manufacturing plant. The simulation uses tasks to simulate individual production lines, with protected objects forming the small inventory areas between production areas.
This is a simple example of tasking and protected types
-----------------------------------------------------------------------------
-- Factory Package
-- Defines a set of task types and communication buffers for the simulation
-- of a factory using "Just In Time" manufacturing techniques.
-----------------------------------------------------------------------------
generic
type Products is (<>);
package Factory is
type Buffers is array(Positive range <>) of Products;
protected type Production_Buffer (Buf_Size : Positive) is
entry Add_Product(Item : in Products);
entry Get_Product(Item : out Products);
private
Buffer : Buffers(1..Buf_Size);
Oldest : Positive := 1;
Newest : Positive := 1;
Count : Natural := 0;
end Production_Buffer;
type Buffer_Access is access Production_Buffer;
task type Producer is
entry Start(Downstream : in Buffer_Access);
entry Halt;
end Producer;
task type Consumer is
entry Start(Upstream : in Buffer_Access);
entry Halt;
end Consumer;
end Factory;
with Ada.Text_Io;
package body Factory is
type Counter is array(Products) of Natural;
--------------
-- Consumer --
--------------
task body Consumer is
Next_Unit : Products;
Conbon : Buffer_Access;
Next_Delay : Duration;
Got_Product : Boolean;
Product_Counts : Counter := (others => 0);
begin
accept Start (Upstream : in Buffer_Access) do
Conbon := Upstream;
end;
Consumption:
loop -- Keep on working until shut down
select
Conbon.Get_Product(Next_Unit);
Got_Product := True;
or
delay 0.05; -- Detect upstream buffer empty
Ada.Text_Io.Put_Line("Upstream buffer empty. Waiting.");
Got_Product := False;
end select;
if Got_Product then
Next_Delay := Duration(Products'Pos(Next_Unit)) * 0.26;
Ada.Text_Io.Put_Line("Consumed " & Products'Image(Next_Unit));
Product_Counts(Next_Unit) := Product_Counts(Next_Unit) + 1;
end if;
select
accept Halt;
Ada.Text_Io.Put_Line("Products Consumed:");
for Index in Product_Counts'range loop
Ada.Text_Io.Put_Line(Products'Image(Index) &
" :" &
Natural'Image(Product_Counts(Index)));
end loop;
exit Consumption;
or
delay Next_Delay; -- Time required to consume a product
end select;
end loop Consumption;
end Consumer;
--------------
-- Producer --
--------------
task body Producer is
Conbon : Buffer_Access;
Next_Delay : Duration;
begin
accept Start(Downstream : in Buffer_Access) do
Conbon := Downstream;
end;
Production_Loop:
loop -- Keep on producing until factory is shut down.
for Unit in Products'range loop
Next_Delay := Duration(Products'Pos(Unit)) * 1.3;
-- delay Next_Delay; -- Time required to produce a unit.
select
Conbon.Add_Product(Unit);
or
delay 0.03; -- Detect full downstream buffer
Ada.Text_Io.Put_Line("Downstream Buffer full." &
" Producer Waiting.");
Conbon.Add_Product(Unit);
end select;
Ada.Text_Io.Put_Line("Produced " & Products'Image(Unit));
select
accept Halt;
exit Production_Loop;
or
delay 0.5; -- Takes 0.5 seconds to produce a unit
end select;
end loop;
end loop Production_Loop;
end Producer;
-----------------------
-- Production_Buffer --
-----------------------
protected body Production_Buffer is
-----------------
-- Add_Product --
-----------------
entry Add_Product (Item : in Products) when Count < Buf_Size is
begin
Buffer(Newest) := Item;
if Newest < Buf_Size then
Newest := Newest + 1;
else
Newest := 1;
end if;
Count := Count + 1;
end Add_Product;
-----------------
-- Get_Product --
-----------------
entry Get_Product (Item : out Products) when Count > 0 is
begin
Item := Buffer(Oldest);
if Oldest < Buf_Size then
Oldest := Oldest + 1;
else
Oldest := 1;
end if;
Count := Count - 1;
end Get_Product;
end Production_Buffer;
end Factory;
-----------------------------------------------------------------------------
-- Factory Manager
-- The Factory_manager procedure defines the factory products,
-- starts the factory, and shuts down the factory.
-----------------------------------------------------------------------------
with Factory;
with Ada.Text_Io;
procedure Factory_Manager is
type Production_Units is (Sonic_Screwdriver,
Stem_Bolt,
Phase_Modulator,
Warp_Convertor,
Subspace_Transducer);
package Synthesizer is new Factory(Production_Units);
use Synthesizer;
Buffer : Buffer_Access := new Production_Buffer(3);
Federation : Producer;
Ferengi_Alliance : Consumer;
begin
Federation.Start(Downstream => Buffer);
Ada.Text_Io.Put_Line("Federation starting production.");
delay 5.0; -- The Ferengis are a little slow tapping into the
-- Federation production system today.
Ferengi_Alliance.Start(Upstream => Buffer);
Ada.Text_Io.Put_Line("Ferengi Alliance starting consumption.");
delay 60.0; -- The manager takes a while to recognize the situation
Federation.Halt;
Ada.Text_Io.Put_Line("Federation production halted.");
delay 1.0; -- The manager must be a Ferengi sympathizer.
Ferengi_Alliance.Halt;
Ada.Text_Io.Put_Line("Ferengi Alliance leaving sector.");
end Factory_Manager;
|