-- Code of Figure 14.9, pages 652-653 from
-- Kenneth C. Louden, Programming Languages
-- Principles and Practice 2nd Edition
-- Copyright (C) Brooks-Cole/ITP, 2003
-- A Bounded Buffer in Ada95

with Text_IO; use Text_IO;

procedure BoundedBuffer is

type StoreType is array (positive range <>) of character;

protected type Buffer (MaxBufferSize: positive) is
  entry insert(ch: in character);
  entry delete(ch: out character);
  function more return boolean;
private
  store: StoreType(1..MaxBufferSize);
  bufferStart: integer := 1;
  bufferEnd: integer := 0;
  bufferSize: integer := 0;
end Buffer;

protected body Buffer is

  entry insert(ch: in character)
    when bufferSize < MaxBufferSize is
  begin
    bufferEnd := bufferEnd mod MaxBufferSize + 1;
    store(bufferEnd) := ch;
    bufferSize := bufferSize + 1;
  end insert;

  entry delete(ch: out CHARACTER)
    when bufferSize > 0 is
  begin
    ch := store(bufferStart);
    bufferStart := bufferStart mod MaxBufferSize + 1;
    bufferSize := bufferSize - 1;
  end delete;

  function more return boolean is
  begin
    return bufferSize > 0;
  end more;

end Buffer;

buf: Buffer(5); -- buffer of size 5

task producer;
task body producer is
ch: character;
begin
  loop
    if (end_of_file) then exit;
    end if;
    if (end_of_line) then
      skip_line;
      -- use carriage return in buf to indicate new line:
      buf.insert(character'(Standard.Ascii.CR));
    else
      get(ch);
      buf.insert(ch);
    end if;
  end loop;
end producer;

task consumer;
task body consumer is
ch: character;
begin
    while (not producer'terminated or buf.more) loop
      buf.delete(ch);
      -- carriage return indicates new line:
      if ch = character'(Standard.Ascii.CR) then
              new_line;
      else put(ch);
      end if;
    end loop;
end Consumer;

begin
  null; -- no code needed, tasks execute automatically
end BoundedBuffer;
