Skip to content

Commit 729ef05

Browse files
committed
controlled types: idiom for refcounting
1 parent 3121390 commit 729ef05

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
=========================================
2+
Reference Counting Using Controlled Types
3+
=========================================
4+
5+
---------------
6+
Global Overview
7+
---------------
8+
9+
* Idiom for counting object references
10+
11+
- Safe deallocation
12+
- No memory leak
13+
- Efficient
14+
- All :ada:`access` must then be using it
15+
16+
* A refcounted type derives from :ada:`Refcounted`
17+
18+
- Tagged
19+
- Get a :ada:`Ref` through :ada:`Set`
20+
- Turn a :ada:`Ref` into an :ada:`access` through :ada:`Get`
21+
22+
.. code:: Ada
23+
24+
package Ref_Counter is
25+
type Refcounted is abstract tagged private;
26+
procedure Free (Self : in out Refcounted) is null;
27+
28+
type Refcounted_Access is access all Refcounted'Class;
29+
type Ref is tagged private;
30+
31+
procedure Set (Self : in out Ref; Data : Refcounted'Class);
32+
function Get (Self : Ref) return Refcounted_Access;
33+
procedure Finalize (P : in out Ref);
34+
procedure Adjust (P : in out Ref);
35+
private
36+
type Refcounted is abstract tagged record
37+
Refcount : Integer := 0;
38+
end record;
39+
40+
type Ref is new Ada.Finalization.Controlled with record
41+
Data : Refcounted_Access;
42+
end record;
43+
44+
----------------------
45+
Implementation Details
46+
----------------------
47+
48+
* :ada:`Set` is safe
49+
50+
- :ada:`Ref` default value is :ada:`null`
51+
- Clears up any previously used :ada:`Ref`
52+
53+
.. code:: Ada
54+
55+
procedure Set (Self : in out Ref; Data : Refcounted'Class) is
56+
D : constant Refcounted_Access := new Refcounted'Class'(Data);
57+
begin
58+
if Self.Data /= null then
59+
Finalize (Self); -- decrement old reference count
60+
end if;
61+
62+
Self.Data := D;
63+
Adjust (Self); -- increment reference count (set to 1)
64+
end Set;
65+
66+
* :ada:`Adjust` called for all new references
67+
68+
.. code:: Ada
69+
70+
overriding procedure Adjust (P : in out Ref) is
71+
begin
72+
if P.Data /= null then
73+
P.Data.Refcount := P.Data.Refcount + 1;
74+
end if;
75+
end Adjust;

courses/fundamentals_of_ada/300_expert_resource_management.rst courses/fundamentals_of_ada/700_expert_resource_management.rst

+1
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ Expert Resource Management
3434
.. container:: PRELUDE END
3535

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

0 commit comments

Comments
 (0)