<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body smarttemplateinserted="true">
    <div id="smartTemplate4-template">Hi,<br>
      <br>
      <p>
        <blockquote type="cite"><br>
          (1) A record is not a pointer. So that would require some
          implicit referencing in the property
          <br>
          <br>
          (2) If it was managed, it would be an allocation, so I don't
          understand this.
          <br>
        </blockquote>
      </p>
      <p><br>
      </p>
      <p>I am talking about replacing interfaces with an record.</p>
      <p>For example this</p>
      <p>/////////////////////////////////////</p>
      <p>type ITest = interface<br>
          procedure println;<br>
        end;<br>
        TTest = class(TInterfacedObject, ITest)<br>
          v: integer;<br>
          constructor Create(av: integer);<br>
          procedure println;<br>
        end;<br>
        <br>
        constructor TTest.Create(av: integer);<br>
        begin<br>
          v := av;<br>
        end;<br>
        <br>
        procedure TTest.println;<br>
        begin<br>
          writeln(v);<br>
        end;<br>
      </p>
      <p>var c: ITest;<br>
        begin<br>
          c := TTest.Create(123);<br>
          c.println;<br>
        /////////////////////////////////</p>
      <p><br>
      </p>
      <p>would become:</p>
      <p><br>
      </p>
      <p>/////////////////////////////////</p>
      type<br>
      <p>TTestRec = class<br>
          rc: Integer;<br>
          v: integer;<br>
          constructor Create(av: integer);<br>
          procedure println;<br>
        end;<br>
        RTest = record<br>
          ptr: TTestRec;<br>
          procedure println; inline;<br>
          class operator :=(c: TTestRec): RTest;<br>
          class operator Initialize(var aRec: RTest);<br>
          class operator finalize(var aRec: RTest);<br>
          class operator AddRef(var aRec: RTest);<br>
        end;<br>
        <br>
        constructor TTestRec.Create(av: integer);<br>
        begin<br>
          v := av;<br>
        end;<br>
        <br>
        procedure TTestRec.println;<br>
        begin<br>
          writeln(v);<br>
        end;<br>
        <br>
        procedure RTest.println;<br>
        begin<br>
          ptr.println; //the wrapper function is inlined<br>
        end;<br>
        <br>
        class operator RTest.:=(c: TTestRec): RTest;<br>
        begin<br>
          result := default(RTest);<br>
          result.ptr := c;<br>
          if c <> nil then<br>
            InterlockedIncrement(c.rc);<br>
        end;<br>
        <br>
        class operator RTest.Initialize(var aRec: RTest);<br>
        begin<br>
          aRec.ptr := nil;<br>
        end;<br>
        <br>
        class operator RTest.finalize(var aRec: RTest);<br>
        begin<br>
          if aRec.ptr <> nil then<br>
            if InterlockedDecrement(aRec.ptr.rc) = 0 then<br>
              aRec.ptr.Free;<br>
        end;<br>
        <br>
        class operator RTest.AddRef(var aRec: RTest);<br>
        begin<br>
          if aRec.ptr <> nil then<br>
            InterlockedIncrement(aRec.ptr.rc);<br>
        end;</p>
      <p>var<br>
            r: RTest;<br>
        begin<br>
          r := TTestRec.Create(123);<br>
          r.println;<br>
        /////////////////////////////////////////////////////////<br>
      </p>
    </div>
    <div>Or even replace the class with a record, too:</div>
    <div><br>
    </div>
    <div><br>
    </div>
    <div>
      <p>/////////////////////////////////////////////////////////<br>
      </p>
      type<br>
      PTestRec2 = ^TTestRec2;<br>
      TTestRec2 = record<br>
        rc: Integer;<br>
        v: integer;<br>
        class function Create(av: integer): PTestRec2; static;<br>
        procedure println;<br>
      end;<br>
      RTest2 = record<br>
        ptr: ^TTestRec2;<br>
        procedure println; inline;<br>
        class operator :=(c: PTestRec2): RTest2;<br>
        class operator Initialize(var aRec: RTest2);<br>
        class operator finalize(var aRec: RTest2);<br>
        class operator AddRef(var aRec: RTest2);<br>
      end;<br>
      <br>
      class function TTestRec2.Create(av: integer): PTestRec2;<br>
      begin<br>
        new(result);<br>
        result^.rc := 0;<br>
        result^.v := av;<br>
      end;<br>
      <br>
      procedure TTestRec2.println;<br>
      begin<br>
        writeln(v);<br>
      end;<br>
      <br>
      procedure RTest2.println;<br>
      begin<br>
        ptr^.println;<br>
      end;<br>
      <br>
      class operator RTest2.:=(c: PTestRec2): RTest2;<br>
      begin<br>
        result := default(RTest2);<br>
        result.ptr := c;<br>
        if c <> nil then<br>
          InterlockedIncrement(c^.rc);<br>
      end;<br>
      <br>
      class operator RTest2.Initialize(var aRec: RTest2);<br>
      begin<br>
        aRec.ptr := nil;<br>
      end;<br>
      <br>
      class operator RTest2.finalize(var aRec: RTest2);<br>
      begin<br>
        if aRec.ptr <> nil then<br>
          if InterlockedDecrement(aRec.ptr^.rc) = 0 then<br>
            dispose(aRec.ptr);<br>
      end;<br>
      <br>
      class operator RTest2.AddRef(var aRec: RTest2);<br>
      begin<br>
        if aRec.ptr <> nil then<br>
          InterlockedIncrement(aRec.ptr^.rc);<br>
      end;<br>
      var</div>
    <div>    r2: RTest2;<br>
      begin<br>
        r2 := TTestRec2.Create(123);<br>
        r2.println;</div>
    <div>/////////////////////////////////////////////////////////<br>
    </div>
    <div>
    </div>
    <div><br>
    </div>
    <div><br>
    </div>
    <div><br>
    </div>
    <div><br>
    </div>
    <div>Not sure if it is actually faster. That needs to be
      investigated.</div>
    <div><br>
    </div>
    <div>But it definitely helps with the memory usage:</div>
    <div><br>
    </div>
    <div>  writeln(ttest.InstanceSize);<br>
        writeln(ttestrec.InstanceSize);<br>
        writeln(sizeof(ttestrec2));<br>
    </div>
    <div><br>
    </div>
    <div>40<br>
      16<br>
      8<br>
      <br>
    </div>
    <div>With many small objects it should be faster just because it
      fits better in the cache.<br>
    </div>
    <div></div>
    <div><br>
      Cheers,<br>
      Benito </div>
    <div class="moz-cite-prefix">On 17.02.21 14:31, Marco van de Voort
      via fpc-pascal wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:c51f7904-379a-ec4f-82a6-54ff8a4e0987@pascalprogramming.org">
      <br>
      Op 2021-02-17 om 00:02 schreef Benito van der Zander via
      fpc-pascal:
      <br>
      <blockquote type="cite">
        <blockquote type="cite">
          <br>
          And there often is a lot of unintentional deep copying. This
          is also why a property returning a record is fairly useless
          except for extremely small records like TPoint (and even that
          is not optimal no </blockquote>
        <br>
        But a managed record to replace an interface, would only contain
        a single pointer/class ref. That can be copied fast
        <br>
      </blockquote>
      <br>
      (1) A record is not a pointer. So that would require some implicit
      referencing in the property
      <br>
      <br>
      (2) If it was managed, it would be an allocation, so I don't
      understand this.
      <br>
      <br>
      <br>
      _______________________________________________
      <br>
      fpc-pascal maillist  -  <a class="moz-txt-link-abbreviated" href="mailto:fpc-pascal@lists.freepascal.org">fpc-pascal@lists.freepascal.org</a>
      <br>
      <a class="moz-txt-link-freetext" href="https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal">https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal</a>
      <br>
    </blockquote>
  </body>
</html>