From f447e5e6b43326645a4990f2039ba728581c6f06 Mon Sep 17 00:00:00 2001 From: rexim Date: Sun, 17 Mar 2024 00:07:38 +0700 Subject: Implement custom ring buffer style queue --- build.sh | 2 +- queue.adb | 43 +++++++++++++++++++++++++++++++++++++++++++ queue.ads | 18 ++++++++++++++++++ test.adb | 31 +++++++++++++++++-------------- 4 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 queue.adb create mode 100644 queue.ads diff --git a/build.sh b/build.sh index fe10404..e276754 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ set -xe -gnatmake -O3 -Wall -Wextra -gnat2022 game.adb -largs -L./raylib/raylib-5.0_linux_amd64/lib/ -l:libraylib.a -lm +gnatmake -Wall -Wextra -gnat2022 game.adb -largs -L./raylib/raylib-5.0_linux_amd64/lib/ -l:libraylib.a -lm ./game # gnatmake -gnat2022 test.adb diff --git a/queue.adb b/queue.adb new file mode 100644 index 0000000..a758224 --- /dev/null +++ b/queue.adb @@ -0,0 +1,43 @@ +with Ada.Unchecked_Deallocation; + +package body Queue is + procedure Delete_Items_Array is new Ada.Unchecked_Deallocation(Items_Array, Items_Array_Access); + + procedure Grow(Q: in out Queue) is + New_Items: Items_Array_Access := new Items_Array(0..Q.Items'Length*2-1); + begin + for Offset in Q.Items'Range loop + New_Items(Offset) := Q.Items((Q.Start + Offset) mod Q.Items'Length); + end loop; + Delete_Items_Array(Q.Items); + Q.Items := New_Items; + Q.Start := 0; + end; + + procedure Enqueue(Q: in out Queue; X: Item) is + begin + if Q.Items = null then + Q.Items := new Items_Array(0..INIT_CAPACITY-1); + end if; + + if Q.Count >= Q.Items'Length then + Grow(Q); + end if; + + Q.Items((Q.Start + Q.Count) mod Q.Items'Length) := X; + Q.Count := Q.Count + 1; + end; + + function Dequeue(Q: in out Queue; X: out Item) return Boolean is + begin + if Q.Count <= 0 then + return False; + end if; + + X := Q.Items(Q.Start); + Q.Start := (Q.Start + 1) mod Q.Items'Length; + Q.Count := Q.Count - 1; + + return True; + end; +end Queue; diff --git a/queue.ads b/queue.ads new file mode 100644 index 0000000..fdfa484 --- /dev/null +++ b/queue.ads @@ -0,0 +1,18 @@ +generic + type Item is private; +package Queue is + INIT_CAPACITY: constant Integer := 256; + + type Items_Array is array (Natural range <>) of Item; + type Items_Array_Access is access Items_Array; + + type Queue is record + Items: Items_Array_Access := null; + Start: Integer := 0; + Count: Integer := 0; + end record; + + procedure Grow(Q: in out Queue); + procedure Enqueue(Q: in out Queue; X: Item); + function Dequeue(Q: in out Queue; X: out Item) return Boolean; +end Queue; diff --git a/test.adb b/test.adb index 115d24e..c74e193 100644 --- a/test.adb +++ b/test.adb @@ -4,21 +4,24 @@ with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Ada.Strings; use Ada.Strings; with Ada.Containers.Vectors; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Queue; procedure Test is - type State is record - X: Integer; - Y: Integer; - end record; - - procedure Foo(S: in State; V: out Integer) is - begin - V := S.X*2; - end; - - S: State := (X => 69, Y => 420); + package String_Queue is new Queue(Item => Unbounded_String); + use String_Queue; + Q: String_Queue.Queue; + X: Unbounded_String; begin - Put_Line(S'Image); - Foo(S, S.Y); - Put_Line(S'Image); + for Index in 1..16 loop + Enqueue(Q, To_Unbounded_String(Index'Image)); + end loop; + while Dequeue(Q, X) loop + null; + end loop; + for Index in 32..42 loop + Enqueue(Q, To_Unbounded_String(Index'Image)); + end loop; + while Dequeue(Q, X) loop + Put_Line(To_String(X)); + end loop; end; -- cgit v1.2.3