As we all known, when we call a constructor of a class like this:
instance := TSomeClass.Create;
The Delphi compiler actually do the following things:
Call the static NewInstance method
to allocate memory and initialize
the memory layout.
Call the constructor method to
perform the initialization of the class
Call the AfterConstruction method
It's simple and easy to understand. but I'm not very sure how the compiler handle exceptions in the second and the third step.
It seems there are no explicit way to create an instance using a RTTI constructor method in D2010. so I wrote a simple function in the Spring Framework for Delphi to reproduce the process of the creation.
class function TActivator.CreateInstance(instanceType: TRttiInstanceType;
constructorMethod: TRttiMethod; const arguments: array of TValue): TObject;
var
classType: TClass;
begin
TArgument.CheckNotNull(instanceType, 'instanceType');
TArgument.CheckNotNull(constructorMethod, 'constructorMethod');
classType := instanceType.MetaclassType;
Result := classType.NewInstance;
try
constructorMethod.Invoke(Result, arguments);
except
on Exception do
begin
if Result is TInterfacedObject then
begin
Dec(TInterfacedObjectHack(Result).FRefCount);
end;
Result.Free;
raise;
end;
end;
try
Result.AfterConstruction;
except
on Exception do
begin
Result.Free;
raise;
end;
end;
end;
I feel it maybe not 100% right. so please show me the way. Thanks!
Invoking the constructor and passing the class as the Self argument (as opposed to an instance) will correctly construct the class. The process of constructing includes the NewInstance, AfterConstruction etc. that you are manually doing here: it's not necessary.
This ought to be sufficient:
Result := constructorMethod.Invoke(instanceType.MetaclassType, arguments);
An oddity of Delphi is how it permits constructors to be called on instances as well as classes. This feature is used as a kind of "placement new" (in C++ terminology) for form construction, so that the global form variable (e.g. Form1 by default for the first form) is assigned at the time that the OnCreate constructor gets invoked. Thus, your code doesn't raise an exception. But it is more normal to pass the class rather than the instance as the Self argument.
Related
Is it mandatory to have Inherited on the first line, in a constructor?
Can I have other code before 'Inherited'?
Example:
constructor TMyIniFile.Create(SectionName: string);
VAR Path: string;
begin
Path:= UserProfileFolder; //initialize path here
inherited Create(Path);
//more code ..
end;
One of the advantages of Delphi's object model (compared to the C++ object model) is the fact that you - as the programmer - can decide WHEN you call the inherited constructor. The code you display in your question is perfectly safe to run.
Also - you can use the instance fields without problem, ie.
CONSTRUCTOR TSomeClass.Create;
BEGIN
FSomeInstanceField:=123;
INHERITED Create;
END;
This will call the inherited constructor, which will have access to the modified value of the FSomeInstanceField variable.
I'm puzzled: why calling a Delphi constructor explicitly / as an ordinary method would not create a new instance / why no memory leaks?
Here's some sample code:
TMyHelperClass = class(TObject)
private
fSomeHelperInt: integer;
public
property SomeHelperInt : integer read fSomeHelperInt write fSomeHelperInt;
constructor Create (const initSomeHelperInt : integer);
end;
TMyClass = class(TObject)
private
fHelper : TMyHelperClass;
public
constructor Create(const initSomeInt: integer);
destructor Destroy; override;
property Helper : TMyHelperClass read fHelper;
end;
Implementation:
constructor TMyHelperClass.Create(const initSomeHelperInt: integer);
begin
fSomeHelperInt := initSomeHelperInt;
end;
constructor TMyClass.Create(const initSomeInt: integer);
begin
fHelper := TMyHelperClass.Create(initSomeInt);
end;
destructor TMyClass.Destroy;
begin
fHelper.Free;
inherited;
end;
And usage:
var
my : TMyClass;
begin
my := TMyClass.Create(2016);
try
//WHY is this ok to be used ?
my.Helper.Create(2017);
finally
my.Free;
end;
end;
How come I could call the TMyHelperClass+s Create constructor as an ordinary method? I mean - this IS exactly as I want it - but how come no issues (with memory)?
I guess the answer will be because the Create method was not called like TMyHelperClass.Create (to create an instance of TMyHelperClass)?
Is this way of calling the constructor as an ordinary method acceptable / ok to be used?
Yes you can call the constructor as an ordinary method.
But it is bad practice to do so.
why no memory leaks?
From: http://docwiki.embarcadero.com/RADStudio/Rio/en/Methods#Constructors
When a constructor is called using an object reference (rather than a
class reference), it does not create an object. Instead, the
constructor operates on the specified object, executing only the
statements in the constructor's implementation, and then returns a
reference to the object. A constructor is typically invoked on an
object reference in conjunction with the reserved word inherited to
execute an inherited constructor.
The compiler will generate different code when calling TObject.Create (class reference) vs AObject.Create (instance reference).
Anti-pattern warning
Abusing the constructor as a normal method will lead to problems when allocating resources.
Normally constructors and destructors are matched, but if you call the constructor twice (as you must when calling the constructor of an instance) you'll allocate the resource twice, but free it only once.
If you want to call the body of the constructor as a normal method, create a new method and call that method in the constructor.
E.g.:
constructor TTest.Create;
begin
inherited;
//Allocate needed resources here.
Init;
end;
procedure TTest.Init;
begin
//Do initialization stuff
//But don't allocate any resources
Now you can safely call the init method whenever needed without any chance of mishaps.
The reason that it's possible to call a constructor without "constructing" anything is that the following code must work:
constructor TTest.Create(const AObject: TObject);
begin //constructor of TTest happens here
inherited Create; //instance call to TParent.Create;
//Other code
end;
In very rare cases you can skip the class call to the constructor entirely.
The following code will work:
MyTest:= TTest.NewInstance;
//Voodoo code here.
MyTest.Create;
This can be used to prevent the compiler from inserting the automatic code that gets generated in a call to TTest.Create.
This is very rarely needed and in 20 years of coding I've only ever used it once.
The use case for this was speed sensitive code where I wanted to avoid the overhead of exception checking and zeroing out of allocated space, this was before Delphi supported records with methods.
If I had to do that code again I'd use a record and just allocate a pool of 1000 records on the heap and hand them out as needed.
I have method with a parameter as object (sniped code below):
TMyObject=class(TObject)
constructor Create();
destructor Destroy();override;
end;
implementation
function doSomething(x:TMyObject):integer;
begin
//code
end;
procedure test();
var
w:integer;
begin
w:=doSomething(TMyObject.Create);
//here: how to free the created object in line above?
end;
How destroy object created inside of called method doSomething outside of this method?
In order to free the object instance, you need to have a reference to it on which you can call Free().
Since you are creating the object instance in-place as a parameter, the only reference you will have is the one inside of the doSomething() parameter.
You either have to Free it inside of doSomething() (which is practice I would not advise doing):
function doSomething(x: TMyObject): Integer;
begin
try
//code
finally
x.Free;
end;
end;
Or, you need to create an additional variable in test(), pass it to doSomething(), and then Free it after doSomething() returns:
procedure test();
var
w: Integer;
o: TMyObject
begin
o := TMyObject.Create;
try
w := doSomething(o);
finally
o.Free;
end;
end;
While one may think that using a reference counted object would allow you to create the object in-place and let reference counting free the object, this kind of construction may not work because of the following compiler issue:
The compiler should keep a hidden reference when passing freshly created object instances directly as const interface parameters
This is confirmed by a former Embarcadero compiler engineer, Barry Kelly, in a StackOverflow answer:
Should the compiler hint/warn when passing object instances directly as const interface parameters?
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I know this is discussed many times everywhere i the community but I just can't find a nice and simple implementation of a Singleton Pattern in Delphi.
I have an example in C#:
public sealed class Singleton {
// Private Constructor
Singleton() { }
// Private object instantiated with private constructor
static readonly Singleton instance = new Singleton();
// Public static property to get the object
public static Singleton UniqueInstance {
get { return instance; }
}
}
I know there is no solution as elegant as this in Delphi and I saw a lot of discussion about no being able to correctly hide the constructor in Delphi (make it private) so we would need to override the NewInstance and FreeInstance methods. Something along those lines I believe is the implementation I found on ibeblog.com - "Delphi: Singleton Patterns":
type
TTestClass = class
private
class var FInstance: TTestClass;
public
class function GetInstance: TTestClass;
class destructor DestroyClass;
end;
{ TTestClass }
class destructor TTestClass.DestroyClass;
begin
if Assigned(FInstance) then
FInstance.Free;
end;
class function TTestClass.GetInstance: TTestClass;
begin
if not Assigned(FInstance) then
FInstance := TTestClass.Create;
Result := FInstance;
end;
What would be your suggestion regarding the Singleton Pattern? Can it be simple and elegant and thread safe?
Thank you.
I think if I wanted an object-like thing that didn't have any means of being constructed I'd probably use an interface with the implementing object contained in the implementation section of a unit.
I'd expose the interface by a global function (declared in the interface section). The instance would be tidied up in a finalization section.
To get thread-safety I'd use either a critical section (or equivalent) or possibly carefully implemented double-checked locking but recognising that naive implementations only work due to the strong nature of the x86 memory model.
It would look something like this:
unit uSingleton;
interface
uses
SyncObjs;
type
ISingleton = interface
procedure DoStuff;
end;
function Singleton: ISingleton;
implementation
type
TSingleton = class(TInterfacedObject, ISingleton)
private
procedure DoStuff;
end;
{ TSingleton }
procedure TSingleton.DoStuff;
begin
end;
var
Lock: TCriticalSection;
_Singleton: ISingleton;
function Singleton: ISingleton;
begin
Lock.Acquire;
Try
if not Assigned(_Singleton) then
_Singleton := TSingleton.Create;
Result := _Singleton;
Finally
Lock.Release;
End;
end;
initialization
Lock := TCriticalSection.Create;
finalization
Lock.Free;
end.
It was mentioned that i should post my answer from over here.
There is a technique called "Lock-free initialization" that does what you want:
interface
function getInstance: TObject;
implementation
var
AObject: TObject;
function getInstance: TObject;
var
newObject: TObject;
begin
if (AObject = nil) then
begin
//The object doesn't exist yet. Create one.
newObject := TObject.Create;
//It's possible another thread also created one.
//Only one of us will be able to set the AObject singleton variable
if InterlockedCompareExchangePointer(AObject, newObject, nil) <> nil then
begin
//The other beat us. Destroy our newly created object and use theirs.
newObject.Free;
end;
end;
Result := AObject;
end;
The use of InterlockedCompareExchangePointer erects a full memory barrier around the operation. It is possible one might be able to get away with InterlockedCompareExchangePointerAcquire or InterlockedCompareExchangeRelease to get away with an optimization by only having a memory fence before or after. The problem with that is:
i'm not smart enough to know if Acquire or Release semantics will work
you're constructing an object, the memory barrier performance hit is the least of your worries (it's the thread safety)
InterlockedCompareExchangePointer
Windows didn't add InterlockedCompareExchangePointer until sometime around 2003. In reality it is simply a wrapper around InterlockedCompareExchange
function InterlockedCompareExchangePointer(var Destination: Pointer; Exchange: Pointer; Comparand: Pointer): Pointer stdcall;
const
SPointerAlignmentError = 'Parameter to InterlockedCompareExchangePointer is not 32-bit aligned';
begin
{IFDEF Debug}
//On 64-bit systems, the pointer must be aligned to 64-bit boundaries.
//On 32-bit systems, the pointer must be aligned to 32-bit boundaries.
if ((NativeInt(Destination) mod 4) <> 0)
or ((NativeInt(Exchange) mod 4) <> 0)
or ((NativeInt(Comparand) mod 4) <> 0) then
begin
OutputDebugString(SPointerAlignmentError);
if IsDebuggerPresent then
Windows.DebugBreak;
end;
{ENDIF}
Result := Pointer(IntPtr(InterlockedCompareExchange(Integer(IntPtr(Destination)), IntPtr(Exchange), IntPtr(Comparand))));
end;
In XE6, i find InterlockedcompareExchangePointer implemented for 32-bit in Windows.Winapi implemented the same way (except for the safety checking):
{$IFDEF WIN32}
function InterlockedCompareExchangePointer(var Destination: Pointer; Exchange: Pointer; Comparand: Pointer): Pointer; inline;
begin
Result := Pointer(IntPtr(InterlockedCompareExchange(Integer(IntPtr(Destination)), IntPtr(Exchange), IntPtr(Comparand))));
end;
{$ENDIF}
In newer versions of Delphi you would, ideally, use the TInterlocked helper class from System.SyncObjs:
if TInterlocked.CompareExchange({var}AObject, newObject, nil) <> nil then
begin
//The other beat us. Destroy our newly created object and use theirs.
newObject.Free;
end;
Note: Any code released into public domain. No attribution required.
The trouble with Delphi is that you always inherit the Create constructor from TObject. But we can deal with that pretty nicely! Here's a way:
TTrueSingleton = class
private
class var FSingle: TTrueSingleton;
constructor MakeSingleton;
public
constructor Create;reintroduce;deprecated 'Don''t use this!';
class function Single: TTrueSingleton;
end;
As you can see we can have a private constructor and we can hide the inherited TObject.Create constructor! In the implementation of TTrueSingleton.Create you can raise an error (run-time block) and the deprecated keyword has the added benefit of providing compile-time error handling!
Here's the implementation part:
constructor TTrueSingleton.Create;
begin
raise Exception.Create('Don''t call me directly!');
end;
constructor TTrueSingleton.MakeSingleton;
begin
end;
class function TTrueSingleton.Single: TTrueSingleton;
begin
if not Assigned(FSingle) then FSingle := TTrueSingleton.MakeSingleton;
Result := FSingle;
end;
If at compile time the compiler sees you doing this:
var X: TTrueSingleton := TTrueSingleton.Create;
it will give you the deprecated warning complete with the provided error message. If you're stubborn enough to ignore it, at run time, you'll not get an object but a raised exception.
Later edit to introduce thread-safety. First of all I must confess, for my own code I don't care about this kind of thread-safety. The probability for two threads accessing my singleton creator routine within such a short time frame it causes two TTrueSingleton objects to be created is so small it's simply not worth the few lines of code required.
But this answer wouldn't be complete without thread safety, so here's my take on the issue. I'll use a simple spin-lock (busy waiting) because it's efficient when no locking needs to be done; Besides, it only locks ones
For this to work an other class var needs to be added: class var FLock: Integer. The Singleton class function should look like this:
class function TTrueSingleton.Single: TTrueSingleton;
var Tmp: TTrueSingleton;
begin
MemoryBarrier; // Make sure all CPU caches are in sync
if not Assigned(FSingle) then
begin
Assert(NativeUInt(#FLock) mod 4 = 0, 'FLock needs to be alligned to 32 bits.');
// Busy-wait lock: Not a big problem for a singleton implementation
repeat
until InterlockedCompareExchange(FLock, 1, 0) = 0; // if FLock=0 then FLock:=1;
try
if not Assigned(FSingle) then
begin
Tmp := TTrueSingleton.MakeSingleton;
MemoryBarrier; // Second barrier, make sure all CPU caches are in sync.
FSingle := Tmp; // Make sure the object is fully created when we assign it to FSingle.
end;
finally FLock := 0; // Release lock
end;
end;
Result := FSingle;
end;
There is a way to hide the inherited “Create” constructor of TObject. Although it is not possible to change the access level, it can be hidden with another public parameterless method with the same name: “Create”. This simplifies the implementation of the Singleton class tremendously. See the simplicity of the code:
unit Singleton;
interface
type
TSingleton = class
private
class var _instance: TSingleton;
public
//Global point of access to the unique instance
class function Create: TSingleton;
destructor Destroy; override;
end;
implementation
{ TSingleton }
class function TSingleton.Create: TSingleton;
begin
if (_instance = nil) then
_instance:= inherited Create as Self;
result:= _instance;
end;
destructor TSingleton.Destroy;
begin
_instance:= nil;
inherited;
end;
end.
I added the details to my original post: http://www.yanniel.info/2010/10/singleton-pattern-delphi.html
The most effective way to make sure something cannot be instantiated is by making it a pure abstract class. That is, if you care enough to heed compiler hints and warnings.
Then define a function in the implementation section that returns a reference to that abstract class. Like Cosmin does in one of his answers.
The implementation section implements that function (you can even make use of lazy instantiation here, as Cosmin also shows/ed).
But the crux is to have a concrete class declared and implemented in the implementation section of the unit so only the unit can instantiated it.
interface
type
TSingleton = class(TObject)
public
procedure SomeMethod; virtual; abstract;
end;
function Singleton: TSingleton;
implementation
var
_InstanceLock: TCriticalSection;
_SingletonInstance: TSingleTon;
type
TConcreteSingleton = class(TSingleton)
public
procedure SomeMethod; override;
end;
function Singleton: TSingleton;
begin
_InstanceLock.Enter;
try
if not Assigned(_SingletonInstance) then
_SingletonInstance := TConcreteSingleton.Create;
Result := _SingletonInstance;
finally
_InstanceLock.Leave;
end;
end;
procedure TConcreteSingleton.SomeMethod;
begin
// FLock can be any synchronisation primitive you like and should of course be
// instantiated in TConcreteSingleton's constructor and freed in its destructor.
FLock.Enter;
try
finally
FLock.Leave;
end;
end;
That said, please bear in mind that there are plenty of problems using singletons: http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/
Thread safety
David is absolutely right in his comment that I was wrong before about the function not needing any protection. The instantiation does indeed need protecting or you could end up with two (possibly more) instances of the singleton and several of them in limbo with regard to freeing (which would be done in the finalization section as with many lazy instantion mechanisms). So here is the amended version.
To get thread safety in this setup, you need to protect the instantiation of the singleton and you need to protect all methods in the concrete class that are publicly available through its abstract ancestor. Other methods do not need to be protected as they are only be callable through the publicly available ones and so are protected by the protection in those methods.
You can protect this by a simple critical section, declared in the implementation, instantiated in the initialization and free in the finalization section. Of course the CS would have to protect the freeing of the singleton as well and should therefore be freed afterwards.
Discussing this with a colleague, we came up with a way to (mis)/(ab)use the instance pointer itself as a sort of lock mechanism. It would work, but I find it to ugly to share with the world at this point in time...
What synchronisation primitives are used to protect the publicly callable methods is entirely up to the "user" (coder) and may tailored to the purpose the singleton.
For threadsafety you should use a lock around the create in "TTestClass.GetInstance".
procedure CreateSingleInstance(aDestination: PPointer; aClass: TClass);
begin
System.TMonitor.Enter(Forms.Application);
try
if aDestination^ = nil then //not created in the meantime?
aDestination^ := aClass.Create;
finally
System.TMonitor.Exit(Forms.Application);
end;
end;
Threadsafe:
if not Assigned(FInstance) then
CreateSingleInstance(#FInstance, TTestClass);
And you could raise an exception in case someone tries to create it via the normal .Create (make a private constructor CreateSingleton)
I'd like to instantiate a class but I only have its name in a string. Is there a way?
This is from Delphi help (Delphi 2006, but also available from at least Delphi 7):
Syntax
function GetClass(const AClassName: string): TPersistentClass;
Description
Call GetClass to obtain a class from a class name. This class can be used as a parameter to routines that require a class. The Class must be registered before GetClass can find it. Form classes and component classes that are referenced in a form declaration (instance variables) are automatically registered when the form is loaded. Other classes can be registered by calling RegisterClass or RegisterClasses .
Here some sample code. Works as such only because TButton is a TControl and therefore the typecast is valid.
procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClasses([TButton, TForm]);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
CRef : TPersistentClass;
AControl : TControl;
begin
CRef := GetClass('TButton');
if CRef<>nil then
begin
AControl := TControl(TControlClass(CRef).Create(Self));
with AControl do
begin
Parent := Self;
Width := 50;
Height := 30;
end;
end;
end;
When I needed to do that, I Built my own Object Factory that uses a specially subclassed TStringList, I'm currently using Delphi 7 so the string list class supports only attach a Object to a String, then I got to subclass TStringList to make it possible handle Class Types too, so now I can instantiate a object just passing it's class name to the factory. Works that way:
1st - Load a Singleton Object Factory;
2st - Register any object to the factory, could be in the initialization section of the unit;
The main Factory's methods could be: isClassRegistered, registerClass, instantiateClass(ClassName: STring): TObject;
This way I can instantiate any object, or use a previous instantiated object, or even, a subset of they.
I rather use a Enumerated type instead of a string to identify a Class.
Remarks: It's a very, very terse example, a completely functional code is more complex, but, belive me, not too much.