Skip to content

Commit

Permalink
controlled types: idiom for refcounting
Browse files Browse the repository at this point in the history
  • Loading branch information
leogermond committed Jan 17, 2025
1 parent 97602c6 commit 9c1e10c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
=========================================
Reference Counting Using Controlled Types
=========================================

---------------
Global Overview
---------------

* Idiom for counting object references

- Safe deallocation
- No memory leak
- Efficient
- All :ada:`access` must then be using it

* A refcounted type derives from :ada:`Refcounted`

- Tagged
- Get a :ada:`Ref` through :ada:`Set`
- Turn a :ada:`Ref` into an :ada:`access` through :ada:`Get`

.. code:: Ada
package Ref_Counter is
type Refcounted is abstract tagged private;
procedure Free (Self : in out Refcounted) is null;
type Refcounted_Access is access all Refcounted'Class;
type Ref is tagged private;
procedure Set (Self : in out Ref; Data : Refcounted'Class);
function Get (Self : Ref) return Refcounted_Access;
procedure Finalize (P : in out Ref);
procedure Adjust (P : in out Ref);
private
type Refcounted is abstract tagged record
Refcount : Integer := 0;
end record;
type Ref is new Ada.Finalization.Controlled with record
Data : Refcounted_Access;
end record;
----------------------
Implementation Details
----------------------

* :ada:`Set` is safe

- :ada:`Ref` default value is :ada:`null`
- Clears up any previously used :ada:`Ref`

.. code:: Ada
procedure Set (Self : in out Ref; Data : Refcounted'Class) is
D : constant Refcounted_Access := new Refcounted'Class'(Data);
begin
if Self.Data /= null then
Finalize (Self); -- decrement old reference count
end if;
Self.Data := D;
Adjust (Self); -- increment reference count (set to 1)
end Set;
* :ada:`Adjust` called for all new references

.. code:: Ada
overriding procedure Adjust (P : in out Ref) is
begin
if P.Data /= null then
P.Data.Refcount := P.Data.Refcount + 1;
end if;
end Adjust;
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ Expert Resource Management
.. container:: PRELUDE END

.. include:: 110_private_types/07-limited-private.rst
.. include:: 260_controlled_types/10-idiom_refcounting.rst

0 comments on commit 9c1e10c

Please sign in to comment.