with Ada.Text_IO; use Ada.Text_IO; procedure Ring_Buffer is type Natural_Array is array (Natural range <>) of Integer; type Ring_Buffer (Capacity : Natural) is record Start_Index : Natural := 0; -- TODO: somehow make these 'mod Size'. Cur_Index : Natural := 0; Empty : Boolean := True; -- TODO: the index type should be 'mod Size'. -- TODO: 0 .. Capacity wastes 1 slot of space. Buffer : Natural_Array (0 .. Capacity) := (others => 0); end record; function Size (RB : Ring_Buffer) return Natural is begin if RB.Empty then return 0; elsif RB.Cur_Index = RB.Start_Index then return RB.Capacity; else return (RB.Cur_Index - RB.Start_Index) mod RB.Capacity; end if; end Size; function Push (RB : in out Ring_Buffer; Value : Integer) return Boolean is begin if Size (RB) = RB.Capacity then return False; else RB.Buffer (RB.Cur_Index) := Value; RB.Cur_Index := (RB.Cur_Index + 1) mod RB.Capacity; RB.Empty := False; return True; end if; end Push; procedure Push (RB : in out Ring_Buffer; Value : Integer) is unused : Boolean := Push (RB, Value); begin return; end Push; function Pop (RB : in out Ring_Buffer; Value : out Integer) return Boolean is begin if Size (RB) = 0 then return False; else Value := RB.Buffer (RB.Start_Index); RB.Start_Index := (RB.Start_Index + 1) mod RB.Capacity; if RB.Start_Index = RB.Cur_Index then RB.Empty := True; end if; return True; end if; end Pop; procedure Pop (RB : in out Ring_Buffer) is Dummy : Integer; unused : Boolean := Pop (RB, Dummy); begin return; end Pop; procedure Print (RB : Ring_Buffer) is begin Put ("["); for I in 0 .. Size (RB) - 1 loop Put (Integer'Image (RB.Buffer ((RB.Start_Index + I) mod RB.Capacity))); end loop; Put_Line ("]"); end Print; Capacity : constant Natural := 5; RB : Ring_Buffer (Capacity); begin Push (RB, 1); Push (RB, 2); Push (RB, 3); Push (RB, 4); Push (RB, 5); -- Full! Push (RB, 6); Push (RB, 7); -- Make some space. Pop (RB); Pop (RB); -- Push more. Push (RB, 8); Push (RB, 9); Print (RB); end Ring_Buffer;