A while ago, there was a nice discussion on smart pointers at [WayBack] Smart Pointers – Generics vrs non-generic implementastion – RTL and Delphi Object Pascal – Delphi-PRAXiS [en].
Conclusion from that:
- many people think that reference counted interfaces are the same as Smart Pointers
(basically Smart Pointers are the next level and of course they are based on reference counting) - there are a lot of Smart Pointer implementations, but few have a test suite, nor are optimised , nor easy to use
- The combo
Shared
/IShared<T>
/TShared<T>
from Spring4D has all of the above advantages - in order to optmise Smart Pointer implementations, you really have to well know the effects of modern Delphi language constructs on the compiler in various target platforms
The discussion mentioned above includes both feature and speed comparisons.
I was a bit amazed that at CodeRage 2018, Marco Cantu introduced yet another smart pointer implementation: one worse than existing implementations, and one with only basic demonstration code, leaving out a test suite.
There have many posts on my blog about smart pointers (see the list below), but Spring4D smart pointer implementation has been around for such a long time that any well respected Delphi developer by now should use them. The source is at Shared/IShared (search for {$REGION 'Shared smart pointer'}
at the current repository).
This list below on my Smart Pointer related blog posts might not be fully complete, but at least mentions that by now you should be using Spring4D.
- Delphi: using IInterface to restore cursor at end of mehod (prelude to a memento that executes any code at end of method). which mentions Smart Pointers as the next level of such
IInterface
usage. - Some great reads from Barry Kelly, which lists a series of great posts that document compiler internals, and explains why they cannot be changed because so much code relies on them
- If you were using Managed / IManaged in Spring4D, be aware they got renamed to Shared / IShared
- How and when are variables referenced in Delphi’s anonymous methods captured? – Stack Overflow
- Spring4D – Shared, Weak references
- Smart Pointers code that compiles in FPC and Delphi
Some comments on the CodeRage 2018 demos
The code is at [WayBack] github.com/marcocantu/DelphiSessions/tree/master/DelphiLanguageCodeRage2018
First a few generic comments:
- With the exception of a few places, none of the demos really explain what they are after, nor indicate where the video or slides can be found. This is not OK for people after the conference bumping into them, and having to find their way back to the original meaning.
- There are duplicated identical files in some of the directories. I think a seasoned Delphi evangelist should should emphasise on good naming and structure next to the actual topic they are after. Fresh Delphi users see these demos and – through their subconscious mind – think this is the organisation to go with. This leads to confirmation bias, which makes it harder to properly educate later on.
- All of the demos use a VCL application plus form to show a language concept. That feels like a lot of overhead, and a missed chance to combine good Delphi language language use with for instance unit testing with DUnit or DUnitX, or even to condense each demo in a simple console application.
- Having some random
TForm##
class names looks very sloppy, giving the wrong signal to developers.
Some comments per demo:
- 01_GenericMethod: GenericForm.pas
- I like the
Result := GetTypeName (TypeInfo (T));
bit as it shows what the compiler can actually get from a generic type. - The demo would be much simpler when
TGenericFunction
was arecord
type instead of aclass
type. - No instance is needed: this could work with
class
methods (for theclass
type) orstatic
class
methods (for therecord
type) just as well. - The demo should emphasise that generic methods are still not possible with global methods that are outside of a type.
- The demo should have shown more on the compiler type inference is shown. That would have given valuable insight on where the inference would have worked and where it would have failed.
- For the “these are all wrong”, the compiler error should have been added as comment to the code so people can understand the errors they might run into when using generic methods.
- I like the
- 02_SmartPointers:
- SmartPointerClass.pas
- Does not explain why it works
- Given that there are no unit tests, and only a few test cases, you have no idea when it works or fails
- SmartPointers_MainForm.pas
- The “implicit create” demo does not indicate if
procedure TSmartPointer<T>.Create;
orconstructor TSmartPointer<T>.Create(AValue: T);
is called implicitly. - The demo parts should have shown which parts of SmartPointerClass.pas are being demoed. It looks like only shows creation and assignment to the
TSmartPointer<T>
based variable and how to obtain the content using theValue
property, but actuallyclass operator TSmartPointer<T>.Implicit(smart: TSmartPointer<T>): T;
is shown as well.
- The “implicit create” demo does not indicate if
- SmartPointerClass.pas
- 03_WeakIntfRef: WeakIntfRef_Form.pas
- Having expanded
Intf
andRef
toInterface
andReference
would have made the aim much clearer. - The demo name suggests
WeakIntfRefAttribute
orWeakRefAttribute
, but the attribute is in factWeakAttribute
which got [Archive.is] template documentation in XE3, but never an update on the real use, apart from a try to “document through a demo” (see below). - Only one aspect of
WeakAttribute
is shown, which fails withoutWeakAttribute
as well: two objects having interface references to each other in the same scope will fail either way. - Contrary to the name, the demo also shows how to use
UnsafeAttribute
which got a [Archive.is] template documentation in XE3, which [Archive.is] got slightly improved in Delphi XE4, only indicating the use of functions results, but nothing added ever since, nor explaining why/how it is considered dangerous.
To set the
unsafe
attribute on a function result, use this syntax:[Result: Unsafe] function ReturnUnsafe: TObject;
Warning:
UnsafeAttribute
should be only used outside theSystem
unit. It is considered dangerous and its use is not recommended. - Way better documentation
WeakRefAttribute
andUnsafeAttribute
of is at[WayBack] Owl’s perspective: DelphiのRTLで定義済の属性 with a great Google translate below.
- Having expanded
- 04_InlineVars: InlineVarsForm.pas
- I like most demos
- The inference demos should describe which type is actually inferred (for instance by showing the
TypeInfo
on the variable) - Demo
Test8
does not explain if theconst
construct is permitted or not.
- 05_InlineVarSpeed: InlineWeird.pas
- This demo should actually explain the measurement differences.
- In addition, this could have been way shorter by refactoring out all but the loop and the actual method calls into common code.
- 06_MoreTypeInference: mtiForm.pas
- Since it is more advanced inference, the inferred types should be shown, especially since
procedure TForm15.Button1Click(Sender: TObject);
is clearly wrong indicating// dynamic array of objects
, but the code demonstrating the inferred type is confined to at leastarray of TComponent
. - I have no idea why
procedure TForm15.Button2Click(Sender: TObject);
is in this demo: it has nothing to do with type inference. - Most demo’s show correct lifetime management using a
try
…finally
construct, butprocedure TForm15.Button2Click(Sender: TObject);
does not. Odd.
- Since it is more advanced inference, the inferred types should be shown, especially since
- 07_BlockScope: BlockScope_Form.pas
- This demo has the same SmartPointerClass.pas unit as 02_SmartPointers. Sloppy.
- The demo shows that inline
var
declarations can be inside abegin
…end
block, but does not show if implicit finalization of Smart Pointers is indeed local to that block, or extended to the method.
So basically this does not show anything more thanprocedure Test5; // scope limited to local block
in InlineVarsForm.pas.
Luckily the thread mentioned above has a great example that does show, which I have quoted further below.
- 07_MissingAttribute:
- Should have bene numbered 08 (small thing, but – like the duplicate files – it gives fresh developers the idea sloppiness is ok)
- MissingAttribute_Form.pas:
- I like that this emphasises
{$WARN UNKNOWN_CUSTOM_ATTRIBUTE ERROR}
, as it got introduced in Delphi 10.3 Rio, but is not documented (see [Archive.is] site:docwiki.embarcadero.com “UNKNOWN_CUSTOM_ATTRIBUTE” – Google Search and [WayBack] Search results for “UNKNOWN_CUSTOM_ATTRIBUTE” – RAD Studio API Documentation, [Archive.is] site:docwiki.embarcadero.com W1074 – Google Search, [WayBack] Search results for “W1074” – RAD Studio)
It means you do not need this Delphi tip of the day: {$WARN UNSUPPORTED_CONSTRUCT ERROR} for W1025 any more.
Note that the documentation still indicates thatW1025
has been documented since at least Delphi 2007 ([WayBack] x1025: Unsupported language feature: ‘%s’) as a C++ header translation issue, and still is ([WayBack] X1025 Unsupported language feature: ‘%s’ (Delphi) – RAD Studio).
- I like that this emphasises
Note I have not watched the above session, as the Embarcadero Academy Terms of Use (which are required to view most CodeRage 2018 sessions) disallow me to use any of that information on my blog: [WayBack/Archive.is] Terms of Use | Embarcadero Academy quote
Use License
- Permission is granted to temporarily download one copy of any downloadable materials on the School’s website for personal, non-commercial transitory viewing only. This is the grant of a license, not a transfer of title, and under this license you may not:
- modify or copy the materials;
- use the materials for any commercial purpose, or for any public display (commercial or non-commercial);
- attempt to decompile or reverse engineer any software contained on the School’s web site;
- remove any copyright or other proprietary notations from the materials; or
- transfer the materials to another person or ‘mirror’ the materials on any other server.
- This license shall automatically terminate if you violate any of these restrictions and may be terminated by Company at any time. Upon terminating your viewing of these materials or upon the termination of this license, you must destroy any downloaded materials in your possession whether in electronic or printed format.
Document through employee blogs outside your company
I think it is not a wise decision to document some new features only outside your own company domain, but on blogs of employees. That is not where your clients search first, so you should get that kind of documentation inside your domain as soon as possible after it gets published outside your domain.
So I like that it is there at all, but dislike it is not on the docwiki: [WayBack] New Delphi 10.3 Warning “Unknown Custom Attribute” (W1074).
Document through demo
Since Delphi XE6, [Archive.is] System.WeakAttribute – RAD Studio API Documentation however points to [Archive.is] RTL.AttributesAndRTTI Sample – RAD Studio Code Examples which leads to [WayBack] RAD Studio Demo Code / Code / [r2029] /branches/RadStudio_XE6/Object Pascal/RTL/AttributesAndRTTI.
As of Delphi RIO [WayBack] System.WeakAttribute – RAD Studio API Documentation, the link in [WayBack] RTL.AttributesAndRTTI Sample – RAD Studio Code Examples is broken ([WayBack] Page not found – SourceForge.net), as nobody bothered to create a new [WayBack] radstudiodemos branch on SourceForge, but the Delphi version rename hobbits did rename everything on the page from Tokyo to Rio.
This means the demo is now inside [WayBack] RADStudio10.3Demos/Object Pascal/RTL/AttributesAndRTTI/rtti_browser at master · Embarcadero/RADStudio10.3Demos · GitHub, which has no Rio
in the URL name, so if the docwiki is fixed, the next mass search/replace there will miss it again.
Anyway: 10.3 Rio demos are at [WayBack] GitHub – Embarcadero/RADStudio10.3Demos: Delphi and C++Builder Demos for Embarcadero RAD Studio version 10.3 Rio
via: “{$WARN UNKNOWN_CUSTOM_ATTRIBUTE ERROR}” – Google Search
Block scope actually frees Smart Pointers at the end of the block
[WayBack] Owl’s perspective: DelphiのRTLで定義済の属性
Google translated is [Archive.is] Delphi RTL defined attributes:
–jeroen
Results with following output