My favorites | Sign in
Project Home Downloads Wiki Issues Source
Checkout   Browse   Changes    
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
-----------------------------------------------------------------------
-- util-refs -- Reference Counting
-- Copyright (C) 2010, 2011 Stephane Carrez
-- Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-----------------------------------------------------------------------
with Ada.Finalization;
with Util.Concurrent.Counters;

-- The <b>Util.Refs</b> package provides support to implement object reference counting.
--
-- The data type to share through reference counting has to inherit from <b>Ref_Entity</b>
-- and the generic package <b>References</b> has to be instantiated.
-- <pre>
-- type Data is new Util.Refs.Ref_Entity with record ... end record;
-- type Data_Access is access all Data;
--
-- package Data_Ref is new Utils.Refs.References (Data, Data_Access);
-- </pre>
--
-- The reference is used as follows:
--
-- <pre>
-- D : Data_Ref.Ref := Data_Ref.Create; -- Allocate and get a reference
-- D2 : Data_Ref.Ref := D; -- Share reference
-- D.Value.all.XXXX := 0; -- Set data member XXXX
-- </pre>
--
-- When a reference is shared in a multi-threaded environment, the reference has to
-- be protected by using the <b>References.Atomic_Ref</b> type.
--
-- R : Data_Ref.Atomic_Ref;
--
-- The reference is then obtained by the protected operation <b>Get</b>.
--
-- D : Data_Ref.Ref := R.Get;
--
package Util.Refs is

-- Root of referenced objects.
type Ref_Entity is abstract tagged limited private;

-- Finalize the referenced object. This is called before the object is freed.
procedure Finalize (Object : in out Ref_Entity) is null;

generic
type Element_Type (<>) is new Ref_Entity with private;
type Element_Access is access all Element_Type;
package Indefinite_References is
type Ref is new Ada.Finalization.Controlled with private;

-- Create an element and return a reference to that element.
function Create (Value : in Element_Access) return Ref;

-- Get the element access value.
function Value (Object : in Ref'Class) return Element_Access;
pragma Inline_Always (Value);

-- Returns true if the reference does not contain any element.
function Is_Null (Object : in Ref'Class) return Boolean;
pragma Inline_Always (Is_Null);

-- The <b>Atomic_Ref</b> protected type defines a reference to an
-- element which can be obtained and changed atomically. The default
-- Ada construct:
--
-- Ref1 := Ref2;
--
-- does not guarantee atomicity of the copy (assignment) and the increment
-- of the reference counter (Adjust operation). To replace shared reference
-- by another one, the whole assignment and Adjust have to be protected.
-- This is achieved by this protected type through the <b>Get</b> and <b>Set</b>
protected type Atomic_Ref is
-- Get the reference
function Get return Ref;

-- Change the reference
procedure Set (Object : in Ref);
private
Value : Ref;
end Atomic_Ref;

private
type Ref is new Ada.Finalization.Controlled with record
Target : Element_Access := null;
end record;

-- Release the reference. Invoke <b>Finalize</b> and free the storage if it was
-- the last reference.
overriding
procedure Finalize (Obj : in out Ref);

-- Update the reference counter after an assignment.
overriding
procedure Adjust (Obj : in out Ref);

end Indefinite_References;

generic
type Element_Type is new Ref_Entity with private;
type Element_Access is access all Element_Type;
package References is
package IR is new Indefinite_References (Element_Type, Element_Access);

subtype Ref is IR.Ref;

-- Create an element and return a reference to that element.
function Create return Ref;

-- The <b>Atomic_Ref</b> protected type defines a reference to an
-- element which can be obtained and changed atomically. The default
-- Ada construct:
--
-- Ref1 := Ref2;
--
-- does not guarantee atomicity of the copy (assignment) and the increment
-- of the reference counter (Adjust operation). To replace shared reference
-- by another one, the whole assignment and Adjust have to be protected.
-- This is achieved by this protected type through the <b>Get</b> and <b>Set</b>
subtype Atomic_Ref is IR.Atomic_Ref;

end References;

private

type Ref_Entity is abstract tagged limited record
Ref_Counter : Util.Concurrent.Counters.Counter;
end record;

end Util.Refs;

Change log

r294 by Stephane.Carrez on Jul 9, 2011   Diff
Remove some renames which are not
necessary
Go to: 
Project members, sign in to write a code review

Older revisions

r293 by Stephane.Carrez on Jul 9, 2011   Diff
Support for references to indefinite
types
- Refactor the References generic
package into a Indefinite_References
  which accept indefinite element
...
r209 by Stephane.Carrez on Apr 3, 2011   Diff
Support for reference countings
All revisions of this file

File info

Size: 5270 bytes, 141 lines
Powered by Google Project Hosting