tinterface4.pp 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. {$mode delphi}
  2. uses variants, sysutils;
  3. (*$ASSERTIONS ON*)
  4. var
  5. fRefCount: Integer = 0;
  6. type
  7. IA = interface
  8. ['{81E19F6A-90C2-11D9-8448-00055DDDEA00}']
  9. end;
  10. TA = class(TObject, IA, IInterface)
  11. destructor Destroy; override;
  12. function _AddRef: Integer; stdcall;
  13. function _Release: Integer; stdcall;
  14. function QueryInterface(const iid: TGuid; out obj): HResult; stdcall;
  15. procedure AfterConstruction; override;
  16. class function NewInstance: TObject; override;
  17. end;
  18. class function TA.NewInstance: TObject;
  19. begin
  20. Result := inherited NewInstance;
  21. fRefCount := 1;
  22. end;
  23. procedure TA.AfterConstruction;
  24. begin
  25. InterlockedDecrement(fRefCount);
  26. inherited AfterConstruction;
  27. end;
  28. function TA._AddRef: Integer; stdcall;
  29. begin
  30. InterlockedIncrement(fRefCount);
  31. Result := 0;
  32. end;
  33. function TA._Release: Integer; stdcall;
  34. begin
  35. InterlockedDecrement(fRefCount);
  36. if fRefCount = 0 then begin
  37. Writeln('Destroy');
  38. Self.Destroy;
  39. end;
  40. Result := 0;
  41. end;
  42. function TA.QueryInterface(const iid: TGuid; out obj): HResult; stdcall;
  43. begin
  44. Result := E_NOINTERFACE;
  45. end;
  46. var
  47. gone: Boolean = False;
  48. destructor TA.Destroy;
  49. begin
  50. gone := True;
  51. Writeln('gone');
  52. inherited Destroy;
  53. end;
  54. procedure X;
  55. var
  56. v: Variant;
  57. i: IInterface;
  58. begin
  59. Writeln('start of test');
  60. (* simple test with nil interface *)
  61. i := nil;
  62. v := i;
  63. i := v;
  64. v := 3;
  65. (* complex test with refcounting *)
  66. Writeln('complex test');
  67. i := TA.Create;
  68. assert(fRefCount = 1);
  69. Writeln('part 1');
  70. v := i;
  71. Writeln('part 2');
  72. //assert(fRefCount = 2);
  73. i := nil;
  74. //assert(fRefCount = 1);
  75. Writeln('part 3');
  76. i := v;
  77. //assert(fRefCount = 2);
  78. Writeln('gone false');
  79. assert(gone = False);
  80. i := nil;
  81. //assert(fRefCount = 1);
  82. assert(gone = False);
  83. v := 7; (* TA refcount 0; gone ... note that v := Null doesnt work for some reason *)
  84. //assert(fRefCount = 0);
  85. Writeln('goo');
  86. //assert(gone = True);
  87. (* "gone" *)
  88. Writeln('okay');
  89. //Halt(0);
  90. end;
  91. begin
  92. X;
  93. end.