<div dir="ltr"><div class="gmail_quote"><div class="gmail_quote">I am working on smart pointers for FPC (something more than pure ARC for classes). </div><div class="gmail_quote"><br></div><div class="gmail_quote">This solution is full compatible with existing code base.</div><div class="gmail_quote"><br></div><div class="gmail_quote">I would like to know what do you think about my conception and work.</div><div class="gmail_quote"><br></div><div class="gmail_quote">First step is almost done -> new record operators:</div><div class="gmail_quote"><br></div><div class="gmail_quote">=== begin code ===</div><div class="gmail_quote">{$MODESWITCH MANAGEMENTOPERATORS}</div><div class="gmail_quote">type // Record with automatic constructor and destructor</div><div class="gmail_quote">  TValue = record</div><div class="gmail_quote">    class operator Initialize(var aRec: TValue);</div><div class="gmail_quote">    class operator Finalize(var aRec: TValue);</div><div class="gmail_quote">    class operator Copy(constref aSource: TValue; var aDest: TValue);</div><div class="gmail_quote">  end;</div><div class="gmail_quote">=== end code ===</div><div class="gmail_quote"><br></div><div class="gmail_quote">MANAGEMENTOPERATORS are quite simple to implement. MANAGEMENTOPERATORS were created initially for fast implementation of TValue in RTTI.pas, but they inspired me for smart pointers.</div><div class="gmail_quote"><br></div><div class="gmail_quote">The second step is some concept of low level structures for smart pointers (in this conception we have two kinds of smart pointers - smart pointers for objects and smart pointers for pointers):</div><div class="gmail_quote"><br></div><div class="gmail_quote">=== code begin ===</div><div class="gmail_quote">  PRawSmartPtr = ^TRawSmartPtr;</div><div class="gmail_quote">  TRawSmartPtr = record</div><div class="gmail_quote">  private</div><div class="gmail_quote">    FInstance: Pointer;</div><div class="gmail_quote">    FRefCount: PLongint;</div><div class="gmail_quote">    function GetInstance: Pointer; </div><div class="gmail_quote">    function GetRefCount: Longint;</div><div class="gmail_quote">  public</div><div class="gmail_quote">    property Instance: Pointer read GetInstance;</div><div class="gmail_quote">    property RefCount: Longint read GetRefCount;</div><div class="gmail_quote">  end;</div><div class="gmail_quote"><br></div><div class="gmail_quote">  PRawSmartObj = ^TRawSmartObj;</div><div class="gmail_quote">  TRawSmartObj = type TRawSmartPtr;</div><div class="gmail_quote"><br></div><div class="gmail_quote">function TRawSmartPtr.GetInstance: Pointer;</div><div class="gmail_quote">begin</div><div class="gmail_quote">  if (FRefCount = nil) or (FRefCount^ <= 0) then</div><div class="gmail_quote">    Exit(nil);</div><div class="gmail_quote">  Result := FInstance;</div><div class="gmail_quote">end;</div><div class="gmail_quote"><br></div><div class="gmail_quote">function TRawSmartPtr.GetRefCount: Longint</div><div class="gmail_quote">begin</div><div class="gmail_quote">  if FRefCount = nil then</div><div class="gmail_quote">    Exit(0);</div><div class="gmail_quote">  Result := FRefCount^;</div><div class="gmail_quote">end;</div><div class="gmail_quote"><br></div><div class="gmail_quote">=== code end ===</div><div class="gmail_quote"><br></div><div class="gmail_quote">For smart pointers we need to implement in some way ".", standard inplicit opertor, "^", "@" and "@@" operator. I thought about it for a long time. IMO minimal invasive method is "default" keyword, used as below:</div><div class="gmail_quote"><br></div><div class="gmail_quote">=== code begin ===</div><div class="gmail_quote">  TSmartPtr<T> = record</div><div class="gmail_quote">    // similar as overloading [] operators for property x[v: string]: integer read gx write sx; default;</div><div class="gmail_quote">    Instance: ^T; default; // default keyword for non property, can be used only for field of pointer type.</div><div class="gmail_quote">    RefCount: PLongint;</div><div class="gmail_quote"><br></div><div class="gmail_quote">    class operator Initialize(var aRec: TSmartPtr<T>);</div><div class="gmail_quote">    class operator Finalize(var aRec: TSmartPtr<T>);</div><div class="gmail_quote">    class operator Copy(constref aSource: TSmartPtr<T>; var aDest: TSmartPtr<T>);</div><div class="gmail_quote"><br></div><div class="gmail_quote">    // implicit or explicit operator should be used before "default" field</div><div class="gmail_quote">    operator Implicit(constref aValue: T); // special version of Implicit/Explicit is also needed (available only when is used default for field)</div><div class="gmail_quote">    operator Explicit: TRawSmartPtr;</div><div class="gmail_quote">  end;</div><div class="gmail_quote"><br></div><div class="gmail_quote">class operator TSmartPtr<T>.Initialize(var aRec: TSmartPtr<T>);</div><div class="gmail_quote">begin</div><div class="gmail_quote">  aRec.RefCount := nil;</div><div class="gmail_quote">end;</div><div class="gmail_quote"><br></div><div class="gmail_quote">class operator TSmartPtr<T>.Finalize(var aRec: TSmartPtr<T>);</div><div class="gmail_quote">begin</div><div class="gmail_quote">  if aRec.RefCount <> nil then</div><div class="gmail_quote">    if InterLockedDecrement(aRec.RefCount^)=0 then</div><div class="gmail_quote">    begin</div><div class="gmail_quote">      Dispose(aRec.RefCount);</div><div class="gmail_quote">      Dispose(aRec.Instance);</div><div class="gmail_quote">    end; </div><div class="gmail_quote">end;</div><div class="gmail_quote"><br></div><div class="gmail_quote">class operator TSmartPtr<T>.Copy(constref aSource: TSmartPtr<T>; var aDest: TSmartPtr<T>);</div><div class="gmail_quote">begin</div><div class="gmail_quote">  if aDest.RefCount <> nil then</div><div class="gmail_quote">    Finalize(aDest);</div><div class="gmail_quote">  if aSource.RefCount <> nil then</div><div class="gmail_quote">    InterLockedIncrement(aSource.RefCount^);</div><div class="gmail_quote">  aDest.RefCount := aSource.RefCount;</div><div class="gmail_quote">  aDest.Instance := aSource.Instance;</div><div class="gmail_quote">end;</div><div class="gmail_quote"><br></div><div class="gmail_quote">operator TSmartPtr<T>.Implicit(constref aValue: T);</div><div class="gmail_quote">begin</div><div class="gmail_quote">  if aDest.RefCount <> nil then</div><div class="gmail_quote">    Finalize(aDest);</div><div class="gmail_quote"><br></div><div class="gmail_quote">  New(RefCount);</div><div class="gmail_quote">  RefCount^ := 0;</div><div class="gmail_quote"><br></div><div class="gmail_quote">  InterLockedIncrement(RefCount^);</div><div class="gmail_quote">  Instance := @aValue;</div><div class="gmail_quote">end;</div><div class="gmail_quote"><br></div><div class="gmail_quote">operator TSmartPtr<T>.Explicit: TRawSmartPtr;</div><div class="gmail_quote">begin</div><div class="gmail_quote">  Result.RefCount := RefCount;</div><div class="gmail_quote">  Result.Instance := Instance;</div><div class="gmail_quote">end;</div><div class="gmail_quote"><br></div><div class="gmail_quote">=== code end ===</div><div class="gmail_quote"><br></div><div class="gmail_quote">TSmartObj<T: TObject> is very similar to TSmartPtr<T>, the difference exist inside Finalize - where is called Instance^.Free method instead of Dispose(aRec.Instance).</div><div class="gmail_quote"><br></div><div class="gmail_quote">few examples:</div><div class="gmail_quote"><br></div><div class="gmail_quote">=== code begin === simple use case</div><div class="gmail_quote">var</div><div class="gmail_quote">  myObj: TSmartObj<TObject>;</div><div class="gmail_quote">begin // <- call Initialize operator</div><div class="gmail_quote">  myObj := TObject.Create; // <- call Implicit operator</div><div class="gmail_quote">end; // <- call Finalize operator. Dec(RefCount) and if RefCount = 0 then call Instance^.Free</div><div class="gmail_quote">=== code end ===</div><div class="gmail_quote"><br></div><div class="gmail_quote"><br></div><div class="gmail_quote">=== code begin === smart pointer and exceptions</div><div class="gmail_quote">var</div><div class="gmail_quote">  myObj: TSmartObj<TObject>;</div><div class="gmail_quote">begin // <- call Initialize operator</div><div class="gmail_quote">  myObj := TObject.Create; // <- call Implicit operator</div><div class="gmail_quote"><br></div><div class="gmail_quote">  try // we don't need try-finally-end anymore because operator Finalize is always called </div><div class="gmail_quote">    WriteLn(myObj.ClassName); // will print TObject. Equivalent of WriteLn(p.Instance^.ClassName);</div><div class="gmail_quote">    raise Exception.Create('Error Message');</div><div class="gmail_quote">  except</div><div class="gmail_quote">    </div><div class="gmail_quote">  end;</div><div class="gmail_quote"><br></div><div class="gmail_quote">end; // <- call Finalize operator. Dec(RefCount) and if RefCount = 0 then call Instance^.Free</div><div class="gmail_quote">=== code end ===</div><div class="gmail_quote"><br></div><div class="gmail_quote">=== code begin === access to TSmartObj/TSmartPtr</div><div class="gmail_quote">var</div><div class="gmail_quote">  p: TSmartPtr<PInteger>;</div><div class="gmail_quote">begin // <- call Initialize operator</div><div class="gmail_quote">  WriteLn(TRawSmartPtr(p).RefCount); // <-- call Explicit . Will print 0</div><div class="gmail_quote">  p := New(PInteger); // <-- call Implicit</div><div class="gmail_quote">  p^ := 10; // use "default" magic, equivalent of p.Instance^^ := 10</div><div class="gmail_quote">  WriteLn(Assigned(p)); // will print true, equivalent of WriteLn(Assigned(p.Instance^));</div><div class="gmail_quote">  WriteLn(TRawSmartPtr(p).RefCount); // <-- call Explicit . Will print 1</div><div class="gmail_quote">end; // <- call Finalize operator. Dec(RefCount) and if RefCount = 0 then call Dispose(Instance)</div><div class="gmail_quote">=== code end ===</div><div class="gmail_quote"><br></div><div class="gmail_quote">and so one :D. This solution is perfect for any Generics.Collections, fpc-stl, fgl library. We can use in simple way weak references and strong references with auto free memory of objects/pointers.</div><div class="gmail_quote"><br></div><div class="gmail_quote">next step is syntax sugar (oxygene compatibility):</div><div class="gmail_quote"><br></div><div class="gmail_quote">var </div><div class="gmail_quote">  SomeObj: unretained TSomeObject; // equivalent of SomeObj: TSomeObject;</div><div class="gmail_quote">  SomeObj: weak TSomeObject; // equivalent of SomeObj: TWeakObj<TSomeObject>; <- TWeakObj is modified version of TSmartObj (to rethink)</div><div class="gmail_quote">  SomeObj: strong TSomeObject; // equivalent of SomeObj: TSmartObj<TSomeObject>;</div><div class="gmail_quote"><br></div><div class="gmail_quote">next step is {$MODE DELPHINEXTGEN} - in this mode any object will be declared as TSmartObj. </div><div class="gmail_quote"><br></div><div class="gmail_quote">-- </div><div class="gmail_quote">Best regards,</div><div class="gmail_quote">Maciej Izak</div></div>
</div>