Menu

[r889]: / trunk / Src / UGC.pas  Maximize  Restore  History

Download this file

223 lines (192 with data), 6.5 kB

  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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
{
* UGC.pas
*
* Provides a garbage collector to assist in maintaining lifetimes of various
* resources.
*
* $Rev$
* $Date$
*
* ***** BEGIN LICENSE BLOCK *****
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is UGC.pas
*
* The Initial Developer of the Original Code is Peter Johnson
* (http://www.delphidabbler.com/).
*
* Portions created by the Initial Developer are Copyright (C) 2009-2010 Peter
* Johnson. All Rights Reserved.
*
* Contributor(s)
* NONE
*
* ***** END LICENSE BLOCK *****
}
unit UGC;
interface
uses
// Project
UBaseObjects;
type
{
TGC:
Static garbage collector class. Used to manage lifetimes of various
resources. Most useful for handling the lifetime of class fields that store
object references - saves explicitly freeing them in finalization sections.
}
TGC = class(TNoConstructObject)
strict private
class procedure GetGC(var GC: IInterface);
{Ensures that a local garbage collector is instantiated.
@param GC [in/out] Garbage collector. If nil a new garbage collector
will be created and stored in GC. If GC is not nil it is checked for
validity and left unchanged.
}
public
class procedure GCLocalObj(var LocalGC: IInterface; const Obj: TObject);
{Adds an object to a local garbage collector instance so that the object
is freed when the garbage collector goes out of scope.
@param LocalGC [in/out] Valid garbage collector to use, or nil. If nil a
new garbage collector is created and stored in LocalGC.
@param Obj [in] Object to place under garbage collection. Obj is added
to LocalGC and freed when LocalGC goes out of scope.
}
end;
implementation
uses
// Project
SysUtils, Classes;
type
{
IGC:
Interface supported by garbage collector objects.
}
IGC = interface(IInterface)
['{61D7BA32-3999-4AD7-A901-4E83A29508F2}']
function AddObject(const Obj: TObject): TObject;
{Adds an object to a garbage collector.
@param Obj [in] Object to be garbage collected.
@return Obj unchanged.
}
// Add futher AddXXX methods for each required resource types
end;
{
TGarbageCollector:
Garbage collector object. Manages a list of resources to be garbage
collected. All the resource are released / freed when the garbage collector
goes out of scope and is destroyed.
}
TGarbageCollector = class(TInterfacedObject, IInterface, IGC)
strict private
fList: TInterfaceList; // List of managed resources
public
constructor Create;
{Class constructor. Sets up object.
}
destructor Destroy; override;
{Class destructor. Releases all resources and tears down object.
}
{ IGC methods }
function AddObject(const Obj: TObject): TObject;
{Adds an object to the list of managed resources. Object will be freed
when garbage collector goes out of scope.
@param Obj [in] Object to be garbage collected.
@return Obj unchanged.
}
end;
{
TGCObjectWrapper:
Interfaced class that wraps another object and automatically frees it when
it goes out of scope.
}
TGCObjectWrapper = class(TInterfacedObject, IInterface)
strict private
fObject: TObject; // Wrapped object
public
constructor Create(Obj: TObject); overload;
{Class constructor. Sets up object wrapper to auto-free another object.
@param Obj [in] Wrapped object.
}
destructor Destroy; override;
{Class destructor. Frees wrapped object.
}
end;
{ TGCObjectWrapper }
constructor TGCObjectWrapper.Create(Obj: TObject);
{Class constructor. Sets up object wrapper to auto-free another object.
@param Obj [in] Wrapped object.
}
begin
Assert(Assigned(Obj), ClassName + '.Create: Obj is nil');
inherited Create;
fObject := Obj;
end;
destructor TGCObjectWrapper.Destroy;
{Class destructor. Frees wrapped object.
}
begin
fObject.Free;
inherited;
end;
{ TGarbageCollector }
function TGarbageCollector.AddObject(const Obj: TObject): TObject;
{Adds an object to the list of managed resources. Object will be freed when
garbage collector goes out of scope.
@param Obj [in] Object to be garbage collected.
@return Obj unchanged.
}
begin
Assert(Assigned(Obj), ClassName + '.AddObject: Obj is nil');
fList.Add(TGCObjectWrapper.Create(Obj));
Result := Obj;
end;
constructor TGarbageCollector.Create;
{Class constructor. Sets up object.
}
begin
inherited Create;
fList := TInterfaceList.Create;
end;
destructor TGarbageCollector.Destroy;
{Class destructor. Releases all resources and tears down object.
}
begin
FreeAndNil(fList); // releases contained interfaced objects
inherited;
end;
{ TGC }
class procedure TGC.GCLocalObj(var LocalGC: IInterface; const Obj: TObject);
{Adds an object to a local garbage collector instance so that the object
is freed when the garbage collector goes out of scope.
@param LocalGC [in/out] Valid garbage collector to use, or nil. If nil a
new garbage collector is created and stored in LocalGC.
@param Obj [in] Object to place under garbage collection. Obj is added
to LocalGC and freed when LocalGC goes out of scope.
}
begin
GetGC(LocalGC);
(LocalGC as IGC).AddObject(Obj);
end;
class procedure TGC.GetGC(var GC: IInterface);
{Ensures that a local garbage collector is instantiated.
@param GC [in/out] Garbage collector. If nil a new garbage collector will be
created and stored in GC. If GC is not nil it is checked for validity and
left unchanged.
}
begin
Assert(not Assigned(GC) or Supports(GC, IGC),
ClassName + '.GetGC: GC is not valid - must support IGC');
if not Assigned(GC) then
GC := TGarbageCollector.Create;
end;
end.
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.