Skip to content

Commit 4a1e464

Browse files
committed
add controlled opengl example
1 parent 3f43290 commit 4a1e464

File tree

3 files changed

+385
-0
lines changed

3 files changed

+385
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
==========================================
2+
Refcounting Wrapper for External C Objects
3+
==========================================
4+
5+
-------
6+
Context
7+
-------
8+
9+
* From :url:`https://blog.adacore.com/the-road-to-a-thick-opengl-binding-for-ada-part-2`
10+
* OpenGL API create various objects like textures or vertex buffers
11+
* Creating them gives us an ID
12+
13+
- Can then be used to refer to the object
14+
15+
* Simple approach: Manually reclaiming them
16+
17+
- Could cause leaks
18+
19+
* Refcount approach: automatic ID management
20+
21+
- From an Ada wrapper
22+
- Automatic reclaim once the last reference vanishes
23+
24+
-----------------
25+
Wrapper Interface
26+
-----------------
27+
28+
* :ada:`type GL_Object is abstract tagged private`
29+
30+
- Implements smart pointer logic
31+
32+
.. code:: Ada
33+
34+
procedure Initialize_Id (Object : in out GL_Object);
35+
36+
procedure Clear (Object : in out GL_Object);
37+
38+
function Initialized (Object : GL_Object) return Boolean;
39+
40+
* Derived by the **actual** object types
41+
42+
.. code:: Ada
43+
44+
procedure Internal_Create_Id
45+
(Object : GL_Object; Id : out UInt) is abstract;
46+
47+
procedure Internal_Release_Id
48+
(Object : GL_Object; Id : UInt) is abstract;
49+
50+
* Example usage
51+
52+
.. code:: Ada
53+
54+
type Shader (Kind : Shader_Type) is new GL_Object with null record;
55+
56+
------------------------------------
57+
Wrapper Implementation: Private part
58+
------------------------------------
59+
60+
* Object ID's holder: :ada:`GL_Object_Reference`
61+
62+
- All derived types have a handle to this
63+
64+
.. code:: Ada
65+
66+
type GL_Object_Reference;
67+
type GL_Object_Reference_Access is access all GL_Object_Reference;
68+
69+
type GL_Object is abstract new Ada.Finalization.Controlled with record
70+
Reference : GL_Object_Reference_Access := null;
71+
end record;
72+
73+
* Controlled implements **ref-counting**
74+
75+
.. code:: Ada
76+
77+
-- Increases reference count.
78+
overriding procedure Adjust (Object : in out GL_Object);
79+
80+
-- Decreases reference count. Destroys texture when it reaches zero.
81+
overriding procedure Finalize (Object : in out GL_Object);
82+
83+
------------------------------------
84+
Wrapper Implementation: Full Picture
85+
------------------------------------
86+
87+
.. code:: Ada
88+
89+
type GL_Object_Reference is record
90+
GL_Id : UInt;
91+
Reference_Count : Natural;
92+
Is_Owner : Boolean;
93+
end record;
94+
95+
.. image:: controlled_gl_object.svg
96+
97+
------------------------
98+
:ada:`Adjust` Completion
99+
------------------------
100+
101+
* :ada:`Adjust` is called every time a new reference is **created**
102+
* Increments the ref-counter
103+
104+
.. code:: Ada
105+
106+
overriding procedure Adjust (Object : in out GL_Object) is
107+
begin
108+
if Object.Reference /= null then
109+
Object.Reference.Reference_Count := @ + 1;
110+
end if;
111+
end Adjust;
112+
113+
--------------------------
114+
:ada:`Finalize` Completion
115+
--------------------------
116+
117+
* :ada:`Finalize` should always be :dfn:`idempotent`
118+
119+
- Compiler might call it multiple times on the same object
120+
- In particular when **exceptions** occur
121+
- Do **not** decrement the reference counter for every call
122+
123+
+ A given object will own **only one** reference
124+
125+
.. code:: Ada
126+
127+
overriding procedure Finalize (Object : in out GL_Object) is
128+
Ref : GL_Object_Reference_Access
129+
renames Object.Reference;
130+
begin
131+
-- Idempotence: the next call to Finalize will have no effect
132+
Ref := null;
133+
134+
if Ref /= null then
135+
Ref.Reference_Count := @ - 1;
136+
if Ref.Reference_Count = 0 then
137+
Free (Ref.all); -- Call to user-defined primitive
138+
Unchecked_Free (Ref);
139+
end if;
140+
end if;
141+
end Finalize;

courses/fundamentals_of_ada/700_expert_resource_management.rst

+1
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ Expert Resource Management
3737
.. include:: 140_access_types/11-idiom_constant_pointer.rst
3838
.. include:: 260_controlled_types/10-idiom_refcounting.rst
3939
.. include:: 260_controlled_types/11-example_logger.rst
40+
.. include:: 230_interfacing_with_c/10-example_refcount_wrap.rst
4041
.. include:: 240_tasking/21-gnat_semaphores.rst

images/controlled_gl_object.svg

+243
Loading

0 commit comments

Comments
 (0)