If you use an implementation of TNonRefCountInterfacedObject, then document in the descendants how lifetime management is arranged for
Posted by jpluimers on 2021/01/21
There are a few TNonRefCountInterfacedObject (or maybe better named TNonReferenceCountedInterfacedObject) implementations around (see list of links below).
They can be used to expose interfaces, but do not provide interface reference counting. This means you have to do your own lifetime management, which can bring quite a few headaches.
So each class you descend from it must have proper motivation on why, and how lifetime management is performed.
One thing you can do is mark the class with a hint directive like [WayBack] library.
In addition, [Archive.is] TNonRefCountInterfacedObject / [Archive.is] TNonReferenceCountedInterfacedObject implementations should at least implement [WayBack] IInterface (or [WayBack] IUnknown in really old Delphi versions); I have seen implementations that don’t but just provide almost empty [WayBack] QueryInterface, [WayBack] _AddRef and [WayBack] _Release methods).
Some examples via “TNonRefCountInterfacedObject” – Google Search:
- [WayBack] Plugin-System Version 3 – Delphi-PRAXiS
- [WayBack] Delphi Knowledge Base: Create an interfaced object with no automatic destruction
- [WayBack] create a base class with a non-reference counted implementation of IUnknown?
Delphi RTL/VLC/FMX
I used this GExperts Grep Search expression to find the entries below:
(_AddRef|_Release|QueryInterface)
Delphi itself has a few implementations of non-standard interface management that have good documentation on their use cases. So take a look at at least these before doing something odd with interface implementations yourself:
- [WayBack]
TAggregatedObjectinSystem- This redirects all
IInterfaceimplementations to a controller - It does not implement
IInterfaceitself, so a descendent must add the interface reference - Descendants are
TContainedObjectandTPropertyPageImpl(the latter used byTActiveXPropertyPage)
- This redirects all
- [WayBack]
TContainedObjectinSystem- This redirects all
IInterfaceimplementations exceptQueryInterfaceto a controller - Descendants are for instance
TSOAPHeaders(viaTSOAPHeadersBase) used byTSoapPascalInvoker,TInvokableClassandTRIO, andTConnectionPointused byTConnectionPoints
- This redirects all
- [WayBack]
TInterfacedPersistentinSystem.Classes- This supports the notion of (potentially) being owned by another
TPersistent. Classes likeTCollectionItem,TFieldOptionsandTEditButtonimplement this ownership behaviour. - When owned, then redirect reference counting to the owner (if that owner implements
IInterface), but notQueryInterface - When not owned, then it is effectively non-reference counted
- This supports the notion of (potentially) being owned by another
- [WayBack]
TComponentinSystem.Classes- This supports the notion of (potentially) being owned by another
TComponent. Classes likeTComponentandTCollectionItemimplement this ownership behaviour. - When owned, then redirects all
IInterfacecalls to the owner (includingQueryInterface).
- This supports the notion of (potentially) being owned by another
- [Archive.is]
TXPEditReaderStreamin DUnitXP_OTAEditorUtils. It is largely undocumented. TXPInterfacedObjectin DUnitXPInterfacedObject. It is largely undocumented too.
Not so good examples:
- [WayBack]
TCustomVariantTypeinSystem.Variants(which is basicallyTSingletonImplementationwith a lot of extra methods) - [WayBack]
TSingletonImplementationinSystem.Generics.Defaults(which is basically what mostTNonRefCountInterfacedObjectimplementations do; this is sort of OK as it is meant to be used only in [WayBack]TCustomComparer<T>and descendants that are supposed to be singletons). IUnknowninWinapi.Ole2(this whole unit is undocumented; the class only has virtual abstract methods; the unit – together withWinapi.OleCtl– seems to be only meant to support the depcrecatedVcl.OleAutounit.)
And of course there is the standard implementation with proper multi-threading support:
- [WayBack]
TInterfacedObjectinSystem
There are quite a few classes that implement reference counting while descending from things like TComponent, usually without the proper multi-threading support that TInferfacedObject has:
- [WayBack]
TStreamedConnectioninDatasnap.Win.SConnect - [WayBack]
TSocketDispatcherThreadinScktMain - [WayBack]
TFDPhysManagerinFireDAC.Phys - [WayBack]
TXPInterfacedObjectin DUnitXPInterfacedObject - [WayBack]
TWeakReferencedObjectin DUnitXDUnitX.WeakReference - [WayBack]
TVirtualWebDirinWeb.Win.AdsTypes - [WayBack]
TEventDispatchExinWebBrowserEx - [WayBack]
TInvokableClassinSoap.InvokeRegistry - [WayBack]
TOleControlinVcl.OleCtrls - [WayBack]
TOleServerinVcl.OleServer - [WayBack]
TUtilsNoRefCountinXml.Internal.AdomCore_4_3
Finally some classes that implement QueryInterface in different ways:
- [WayBack]
TCustomWrapperinSystem.Bindings.CustomWrapper - [WayBack]
TLocationWrapperinSystem.Bindings.EvalProtocol - [WayBack]
TNestedScopeinSystem.Bindings.EvalSys - [WayBack]
TAbstractMemberInstanceand [WayBack]TVirtualObjectMemberInstanceinSystem.Bindings.ObjEval - [WayBack]
TPresentedControlinFMX.Controls.Presentation - [WayBack]
TCommonCustomForminFMX.Forms - [WayBack]
THTMLElementEventDispatchinWebBrowserEx - [WayBack]
TRawVirtualClassand [WayBack]TVirtualInterfaceinSystem.Rtti - [WayBack]
TComObjectand [WayBack]TComObjectFactoryand [WayBack]TDispatchSilencerinSystem.Win.ComObj - [WayBack]
TEventDispatchand [WayBack]TDelegatedOleControlinSystem.Win.OleControls - [WayBack]
TServerEventDispatchand [WayBack]TOleServerinSystem.Win.OleServers - [WayBack]
TInvokableClassinSoap.InvokeRegistry - [WayBack]
TRIOand [WayBack]TRIO.TRioVirtualInterfaceinSoap.Rio - [WayBack]
THTTPRIOinSoap.SOAPHTTPClient - [WayBack]
TLinkedRIOinSoap.SOAPLinked - [WayBack]
TOleLinkStubinVcl.AxCtrls - [WayBack]
TCustomForminVcl.Forms- [WayBack]
TAutoDispatchand [WayBack]TAutoObjectand [WayBack]TClassFactoryinVcl.OleAuto
- [WayBack]
- [WayBack]
TOleContainerinVcl.OleCtnrs - [WayBack]
TEventDispatchinVcl.OleCtrls - [WayBack]
TServerEventDispatchinVcl.OleServer
–jeroen






Leave a comment