Hello

Hello,

I've write some code to make purists cry :)

ARC on Records !

if Google can't translate the french page, just look a the code at the bottom of the page ;)

http://lookinside.free.fr/delphi.php?Destructor+sur+un+Record

Comments

  1. Is French `Mon` the same as English `My`?

    ReplyDelete
  2. I prefer abusing Anonymous methods: courtesy of Barry Kelly - http://blog.barrkel.com/2008/11/reference-counted-pointers-revisited.html

    --8<--
    unit ObjHandle2;

    interface

    uses SysUtils;

    type
    TObjectHandle = class(TInterfacedObject, TFunc)
    private
    FValue: T;
    public
    constructor Create(AValue: T);
    destructor Destroy; override;
    function Invoke: T;
    end;

    implementation

    constructor TObjectHandle.Create(AValue: T);
    begin
    FValue := AValue;
    end;

    destructor TObjectHandle.Destroy;
    begin
    FValue.Free;
    end;

    function TObjectHandle.Invoke: T;
    begin
    Result := FValue;
    end;

    end.
    ->8---
    blog.barrkel.com - Entropy Overload: Smart pointers in Delphi

    ReplyDelete
  3. Jeroen Wiert Pluimers yes, "mon objet" is "my object", and "ma classe" is "my class", we don't have neutral gender in french..

    ReplyDelete
  4. Dalija Prasnikar the purpose of my solution is to avoid any dynamic allocation, the record is fully static on the heap :)

    ReplyDelete
  5. You can't out the record on the heap without dynamic allocation. That makes no sense. Did you mean that it's on the stack. It will be for a local variable. What about when it's the member field of a class?

    ReplyDelete
  6. Paul TOTH You are already allocating wrapped object. If you are at point where it matters whether wrapper is heap or stack allocated, you should not be using SmartPointers anyway.

    Also, since it is a record you cannot pass your wrapper around unless you consort passing it as pointer...

    ReplyDelete
  7. David Heffernan my mistake, I mean "stack" and not heap of course..."pile" in french vs "tas".
    If it's member of a class, it will works also because Delphi calls finalize on the record, and finalize call the _Release method of the Interface.

    ReplyDelete
  8. Dalija Prasnikar I don't understand your last sentence...anyway this hack is a way to automatic call a destructor for a static record, my sample code use an Object but it can be anything else, like closing a file, releasing a pointer. Using an object with a overrided destructor was just an easy proof of concept.

    ReplyDelete
  9. Paul TOTH What I meant when I said that you cannot pass record instance around is, since it is value type, you have to be careful not to make copies of it.

    ReplyDelete
  10. It's clever, it can sometimes be useful

    ReplyDelete
  11. I've added two samples, one for Delphi 6, and the other with the "object" keyword, note that it works under Tokyo, but under Delphi 6, the herited interface is NOT released !

    ReplyDelete
  12. Apart from the Barry Kelly implementation, you should also look at the Smart Pointer implementation and surrounding data types IManaged, TManaged, Managed and Managed in bitbucket.org - sglienke / Spring4D
    / source / Source / Base / Spring.pas
    — Bitbucket


    Doesn't work in Delphi 6 (likely fails in anything below Delphi XE) but for me those are a thing from the past.

    ReplyDelete
  13. Jeroen Wiert Pluimers well Managed instanciate a TManaged, it's to avoid this allocation that my record use a "hacked" Interface )

    Anyway, it was just a toy for me, I'm not sure I'll use it in production.

    I've explored this because of my implementation of GDI+ flat API

    TGraphics = record
    private
    Handle : Pointer;
    public
    function Create(ADC: HDC): TStatus; inline;
    ...
    // GDI+ Graphics functions wrappers goes here
    ...
    procedure Free; inline;
    end;

    function GdipCreateFromHDC(ADC: HDC; out AGraphics: TGraphics): TStatus; stdcall; external GDIP;
    function GdipDeleteGraphics(var AGraphics: TGraphics): TStatus; stdcall; external GDIP;

    function TGraphics.Create(ADC: HDC): TStatus;
    begin
    Result := GdipCreateFromHDC(ADC, Self);
    end;

    procedure TGraphics.Free;
    begin
    GdipDeleteGraphics(Self);
    end;

    var
    G: TGrapchis;
    begin
    G.Create(Canvas.Handle);
    ....
    G.Free;
    end

    ReplyDelete
  14. Très bien mais quel intérêt?

    ReplyDelete
  15. Didier Tactisoft if you don't know what a destructor is for...I can't help you...même en français :)

    ReplyDelete

Post a Comment