objpas.inc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team
  4. This unit makes Free Pascal as much as possible Delphi compatible
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {****************************************************************************
  12. Internal Routines called from the Compiler
  13. ****************************************************************************}
  14. { the reverse order of the parameters make code generation easier }
  15. function fpc_do_is(aclass : tclass;aobject : tobject) : boolean;[public,alias: 'FPC_DO_IS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  16. begin
  17. fpc_do_is:=assigned(aobject) and assigned(aclass) and
  18. aobject.inheritsfrom(aclass);
  19. end;
  20. { the reverse order of the parameters make code generation easier }
  21. function fpc_do_as(aclass : tclass;aobject : tobject): tobject;[public,alias: 'FPC_DO_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  22. begin
  23. if assigned(aobject) and not(aobject.inheritsfrom(aclass)) then
  24. handleerrorframe(219,get_frame);
  25. result := aobject;
  26. end;
  27. { interface helpers }
  28. procedure fpc_intf_decr_ref(var i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[public,alias: 'FPC_INTF_DECR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  29. begin
  30. if assigned(i) then
  31. IUnknown(i)._Release;
  32. i:=nil;
  33. end;
  34. {$ifdef hascompilerproc}
  35. { local declaration for intf_decr_ref for local access }
  36. procedure intf_decr_ref(var i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif} [external name 'FPC_INTF_DECR_REF'];
  37. {$endif hascompilerproc}
  38. procedure fpc_intf_incr_ref(i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif}[public,alias: 'FPC_INTF_INCR_REF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  39. begin
  40. if assigned(i) then
  41. IUnknown(i)._AddRef;
  42. end;
  43. {$ifdef hascompilerproc}
  44. { local declaration of intf_incr_ref for local access }
  45. procedure intf_incr_ref(i: pointer);{$ifndef NOSAVEREGISTERS}saveregisters;{$endif} [external name 'FPC_INTF_INCR_REF'];
  46. {$endif hascompilerproc}
  47. procedure fpc_intf_assign(var D: pointer; const S: pointer);[public,alias: 'FPC_INTF_ASSIGN']; {$ifdef hascompilerproc} compilerproc; {$endif}
  48. begin
  49. if assigned(S) then
  50. IUnknown(S)._AddRef;
  51. if assigned(D) then
  52. IUnknown(D)._Release;
  53. D:=S;
  54. end;
  55. function fpc_intf_as(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_INTF_AS']; {$ifdef hascompilerproc} compilerproc; {$endif}
  56. var
  57. tmpi: pointer; // _AddRef before _Release
  58. begin
  59. if assigned(S) then
  60. begin
  61. if IUnknown(S).QueryInterface(iid,tmpi)<>S_OK then
  62. handleerror(219);
  63. fpc_intf_as:=tmpi;
  64. end
  65. else
  66. fpc_intf_as:=nil;
  67. end;
  68. function fpc_class_as_intf(const S: pointer; const iid: TGUID): pointer;[public,alias: 'FPC_CLASS_AS_INTF']; {$ifdef hascompilerproc} compilerproc; {$endif}
  69. var
  70. tmpi: pointer; // _AddRef before _Release
  71. begin
  72. if assigned(S) then
  73. begin
  74. if not TObject(S).GetInterface(iid,tmpi) then
  75. handleerror(219);
  76. fpc_class_as_intf:=tmpi;
  77. end
  78. else
  79. fpc_class_as_intf:=nil;
  80. end;
  81. {****************************************************************************
  82. TOBJECT
  83. ****************************************************************************}
  84. constructor TObject.Create;
  85. begin
  86. end;
  87. destructor TObject.Destroy;
  88. begin
  89. end;
  90. procedure TObject.Free;
  91. begin
  92. // the call via self avoids a warning
  93. if self<>nil then
  94. self.destroy;
  95. end;
  96. class function TObject.InstanceSize : LongInt;
  97. begin
  98. InstanceSize:=plongint(pointer(self)+vmtInstanceSize)^;
  99. end;
  100. procedure InitInterfacePointers(objclass: tclass;instance : pointer);
  101. var
  102. intftable : pinterfacetable;
  103. i : longint;
  104. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  105. IOffset : longint;
  106. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  107. begin
  108. while assigned(objclass) do
  109. begin
  110. intftable:=pinterfacetable((pointer(objclass)+vmtIntfTable)^);
  111. if assigned(intftable) then
  112. for i:=0 to intftable^.EntryCount-1 do
  113. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  114. begin
  115. move(intftable^.Entries[i].IOffset,IOffset,sizeof(longint));
  116. move(pointer(intftable^.Entries[i].VTable),ppointer(@(PChar(instance)[IOffset]))^,sizeof(pointer));
  117. end;
  118. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  119. ppointer(@(PChar(instance)[intftable^.Entries[i].IOffset]))^:=
  120. pointer(intftable^.Entries[i].VTable);
  121. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  122. objclass:=pclass(pointer(objclass)+vmtParent)^;
  123. end;
  124. end;
  125. class function TObject.InitInstance(instance : pointer) : tobject;
  126. begin
  127. { the size is saved at offset 0 }
  128. fillchar(instance^,plongint(pointer(self)+vmtInstanceSize)^,0);
  129. { insert VMT pointer into the new created memory area }
  130. { (in class methods self contains the VMT!) }
  131. ppointer(instance)^:=pointer(self);
  132. InitInterfacePointers(self,instance);
  133. InitInstance:=TObject(Instance);
  134. end;
  135. class function TObject.ClassParent : tclass;
  136. begin
  137. { type of self is class of tobject => it points to the vmt }
  138. { the parent vmt is saved at offset vmtParent }
  139. classparent:=pclass(pointer(self)+vmtParent)^;
  140. end;
  141. class function TObject.NewInstance : tobject;
  142. var
  143. p : pointer;
  144. begin
  145. getmem(p,plongint(pointer(self)+vmtInstanceSize)^);
  146. if p <> nil then
  147. InitInstance(p);
  148. NewInstance:=TObject(p);
  149. end;
  150. procedure TObject.FreeInstance;
  151. begin
  152. CleanupInstance;
  153. FreeMem(Pointer(Self));
  154. end;
  155. class function TObject.ClassType : TClass;
  156. begin
  157. ClassType:=TClass(Pointer(Self))
  158. end;
  159. type
  160. tmethodnamerec = packed record
  161. name : pshortstring;
  162. addr : pointer;
  163. end;
  164. tmethodnametable = packed record
  165. count : dword;
  166. entries : packed array[0..0] of tmethodnamerec;
  167. end;
  168. pmethodnametable = ^tmethodnametable;
  169. class function TObject.MethodAddress(const name : shortstring) : pointer;
  170. var
  171. UName : ShortString;
  172. methodtable : pmethodnametable;
  173. i : dword;
  174. vmt : tclass;
  175. begin
  176. UName := UpCase(name);
  177. vmt:=self;
  178. while assigned(vmt) do
  179. begin
  180. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  181. if assigned(methodtable) then
  182. begin
  183. for i:=0 to methodtable^.count-1 do
  184. if UpCase(methodtable^.entries[i].name^)=UName then
  185. begin
  186. MethodAddress:=methodtable^.entries[i].addr;
  187. exit;
  188. end;
  189. end;
  190. vmt:=pclass(pointer(vmt)+vmtParent)^;
  191. end;
  192. MethodAddress:=nil;
  193. end;
  194. class function TObject.MethodName(address : pointer) : shortstring;
  195. var
  196. methodtable : pmethodnametable;
  197. i : dword;
  198. vmt : tclass;
  199. begin
  200. vmt:=self;
  201. while assigned(vmt) do
  202. begin
  203. methodtable:=pmethodnametable((Pointer(vmt)+vmtMethodTable)^);
  204. if assigned(methodtable) then
  205. begin
  206. for i:=0 to methodtable^.count-1 do
  207. if methodtable^.entries[i].addr=address then
  208. begin
  209. MethodName:=methodtable^.entries[i].name^;
  210. exit;
  211. end;
  212. end;
  213. vmt:=pclass(pointer(vmt)+vmtParent)^;
  214. end;
  215. MethodName:='';
  216. end;
  217. function TObject.FieldAddress(const name : shortstring) : pointer;
  218. type
  219. PFieldInfo = ^TFieldInfo;
  220. TFieldInfo =
  221. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  222. packed
  223. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  224. record
  225. FieldOffset: PtrUInt;
  226. ClassTypeIndex: Word;
  227. Name: ShortString;
  228. end;
  229. PFieldTable = ^TFieldTable;
  230. TFieldTable =
  231. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  232. packed
  233. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  234. record
  235. FieldCount: Word;
  236. ClassTable: Pointer;
  237. { should be array[Word] of TFieldInfo; but
  238. Elements have variant size! force at least proper alignment }
  239. Fields: array[0..0] of TFieldInfo
  240. end;
  241. var
  242. UName: ShortString;
  243. CurClassType: TClass;
  244. FieldTable: PFieldTable;
  245. FieldInfo: PFieldInfo;
  246. i: Integer;
  247. begin
  248. if Length(name) > 0 then
  249. begin
  250. UName := UpCase(name);
  251. CurClassType := ClassType;
  252. while CurClassType <> nil do
  253. begin
  254. FieldTable := PFieldTable((Pointer(CurClassType) + vmtFieldTable)^);
  255. if FieldTable <> nil then
  256. begin
  257. FieldInfo := @FieldTable^.Fields;
  258. for i := 0 to FieldTable^.FieldCount - 1 do
  259. begin
  260. if UpCase(FieldInfo^.Name) = UName then
  261. begin
  262. fieldaddress := Pointer(Self) + FieldInfo^.FieldOffset;
  263. exit;
  264. end;
  265. FieldInfo := @FieldInfo^.Name + 1 + Length(FieldInfo^.Name);
  266. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  267. { align to largest field of TFieldInfo }
  268. FieldInfo := Align(FieldInfo, SizeOf(PtrUInt));
  269. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  270. end;
  271. end;
  272. { Try again with the parent class type }
  273. CurClassType:=pclass(pointer(CurClassType)+vmtParent)^;
  274. end;
  275. end;
  276. fieldaddress:=nil;
  277. end;
  278. function TObject.SafeCallException(exceptobject : tobject;
  279. exceptaddr : pointer) : longint;
  280. begin
  281. safecallexception:=0;
  282. end;
  283. class function TObject.ClassInfo : pointer;
  284. begin
  285. ClassInfo:=ppointer(Pointer(self)+vmtTypeInfo)^;
  286. end;
  287. class function TObject.ClassName : ShortString;
  288. begin
  289. ClassName:=PShortString((Pointer(Self)+vmtClassName)^)^;
  290. end;
  291. class function TObject.ClassNameIs(const name : string) : boolean;
  292. begin
  293. ClassNameIs:=Upcase(ClassName)=Upcase(name);
  294. end;
  295. class function TObject.InheritsFrom(aclass : TClass) : Boolean;
  296. var
  297. vmt : tclass;
  298. begin
  299. vmt:=self;
  300. while assigned(vmt) do
  301. begin
  302. if vmt=aclass then
  303. begin
  304. InheritsFrom:=true;
  305. exit;
  306. end;
  307. vmt:=pclass(pointer(vmt)+vmtParent)^;
  308. end;
  309. InheritsFrom:=false;
  310. end;
  311. class function TObject.stringmessagetable : pstringmessagetable;
  312. type
  313. pdword = ^dword;
  314. begin
  315. stringmessagetable:=pstringmessagetable((pointer(Self)+vmtMsgStrPtr)^);
  316. end;
  317. type
  318. tmessagehandler = procedure(var msg) of object;
  319. tmessagehandlerrec = packed record
  320. proc : pointer;
  321. obj : pointer;
  322. end;
  323. procedure TObject.Dispatch(var message);
  324. type
  325. tmsgtable = packed record
  326. index : dword;
  327. method : pointer;
  328. end;
  329. pmsgtable = ^tmsgtable;
  330. var
  331. index : dword;
  332. count,i : longint;
  333. msgtable : pmsgtable;
  334. p : pointer;
  335. vmt : tclass;
  336. msghandler : tmessagehandler;
  337. begin
  338. index:=dword(message);
  339. vmt:=ClassType;
  340. while assigned(vmt) do
  341. begin
  342. // See if we have messages at all in this class.
  343. p:=pointer(vmt)+vmtDynamicTable;
  344. If Assigned(p) and (Pdword(p)^<>0) then
  345. begin
  346. msgtable:=pmsgtable(PtrInt(p^)+4);
  347. count:=pdword(p^)^;
  348. end
  349. else
  350. Count:=0;
  351. { later, we can implement a binary search here }
  352. for i:=0 to count-1 do
  353. begin
  354. if index=msgtable[i].index then
  355. begin
  356. p:=msgtable[i].method;
  357. tmessagehandlerrec(msghandler).proc:=p;
  358. tmessagehandlerrec(msghandler).obj:=self;
  359. msghandler(message);
  360. exit;
  361. end;
  362. end;
  363. vmt:=pclass(pointer(vmt)+vmtParent)^;
  364. end;
  365. DefaultHandler(message);
  366. end;
  367. procedure TObject.DispatchStr(var message);
  368. type
  369. PSizeUInt = ^SizeUInt;
  370. var
  371. name : shortstring;
  372. count,i : longint;
  373. msgstrtable : pmsgstrtable;
  374. p : pointer;
  375. vmt : tclass;
  376. msghandler : tmessagehandler;
  377. begin
  378. name:=pshortstring(@message)^;
  379. vmt:=ClassType;
  380. while assigned(vmt) do
  381. begin
  382. p:=(pointer(vmt)+vmtMsgStrPtr);
  383. If (P<>Nil) and (PDWord(P)^<>0) then
  384. begin
  385. count:=pdword(PSizeUInt(p)^)^;
  386. msgstrtable:=pmsgstrtable(PSizeUInt(P)^+4);
  387. end
  388. else
  389. Count:=0;
  390. { later, we can implement a binary search here }
  391. for i:=0 to count-1 do
  392. begin
  393. if name=msgstrtable[i].name^ then
  394. begin
  395. p:=msgstrtable[i].method;
  396. tmessagehandlerrec(msghandler).proc:=p;
  397. tmessagehandlerrec(msghandler).obj:=self;
  398. msghandler(message);
  399. exit;
  400. end;
  401. end;
  402. vmt:=pclass(pointer(vmt)+vmtParent)^;
  403. end;
  404. DefaultHandlerStr(message);
  405. end;
  406. procedure TObject.DefaultHandler(var message);
  407. begin
  408. end;
  409. procedure TObject.DefaultHandlerStr(var message);
  410. begin
  411. end;
  412. procedure TObject.CleanupInstance;
  413. Type
  414. TRecElem = packed Record
  415. Info : Pointer;
  416. Offset : Longint;
  417. end;
  418. TRecElemArray = packed array[1..Maxint] of TRecElem;
  419. PRecRec = ^TRecRec;
  420. TRecRec = record
  421. Size,Count : Longint;
  422. Elements : TRecElemArray;
  423. end;
  424. var
  425. vmt : tclass;
  426. temp : pbyte;
  427. count,
  428. i : longint;
  429. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  430. recelem : TRecElem;
  431. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  432. begin
  433. vmt:=ClassType;
  434. while vmt<>nil do
  435. begin
  436. { This need to be included here, because Finalize()
  437. has should support for tkClass }
  438. Temp:=Pointer((Pointer(vmt)+vmtInitTable)^);
  439. if Assigned(Temp) then
  440. begin
  441. inc(Temp);
  442. I:=Temp^;
  443. inc(temp,I+1); // skip name string;
  444. {$ifdef FPC_ALIGNSRTTI}
  445. temp:=aligntoptr(temp);
  446. {$endif FPC_ALIGNSRTTI}
  447. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  448. move(PRecRec(Temp)^.Count,Count,sizeof(Count));
  449. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  450. Count:=PRecRec(Temp)^.Count; // get element Count
  451. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  452. For I:=1 to count do
  453. {$ifdef FPC_REQUIRES_PROPER_ALIGNMENT}
  454. begin
  455. move(PRecRec(Temp)^.elements[I],RecElem,sizeof(RecElem));
  456. With RecElem do
  457. int_Finalize (pointer(self)+Offset,Info);
  458. end;
  459. {$else FPC_REQUIRES_PROPER_ALIGNMENT}
  460. With PRecRec(Temp)^.elements[I] do
  461. int_Finalize (pointer(self)+Offset,Info);
  462. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  463. end;
  464. vmt:=pclass(pointer(vmt)+vmtParent)^;
  465. end;
  466. end;
  467. procedure TObject.AfterConstruction;
  468. begin
  469. end;
  470. procedure TObject.BeforeDestruction;
  471. begin
  472. end;
  473. function IsGUIDEqual(const guid1, guid2: tguid): boolean;
  474. begin
  475. IsGUIDEqual:=
  476. (guid1.D1=guid2.D1) and
  477. (PDWORD(@guid1.D2)^=PDWORD(@guid2.D2)^) and
  478. (PDWORD(@guid1.D4[0])^=PDWORD(@guid2.D4[0])^) and
  479. (PDWORD(@guid1.D4[4])^=PDWORD(@guid2.D4[4])^);
  480. end;
  481. function TObject.getinterface(const iid : tguid;out obj) : boolean;
  482. var
  483. IEntry: pinterfaceentry;
  484. begin
  485. IEntry:=getinterfaceentry(iid);
  486. if Assigned(IEntry) then
  487. begin
  488. Pointer(obj):=Pointer(Self)+IEntry^.IOffset;
  489. if assigned(pointer(obj)) then
  490. iinterface(obj)._AddRef;
  491. getinterface:=True;
  492. end
  493. else
  494. begin
  495. PPointer(@Obj)^:=nil;
  496. getinterface:=False;
  497. end;
  498. end;
  499. function TObject.getinterfacebystr(const iidstr : string;out obj) : boolean;
  500. var
  501. IEntry: pinterfaceentry;
  502. begin
  503. IEntry:=getinterfaceentrybystr(iidstr);
  504. if Assigned(IEntry) then
  505. begin
  506. Pointer(obj):=Pointer(Self)+IEntry^.IOffset;
  507. if assigned(pointer(obj)) then
  508. iinterface(obj)._AddRef;
  509. getinterfacebystr:=True;
  510. end
  511. else
  512. begin
  513. PPointer(@Obj)^:=nil;
  514. getinterfacebystr:=False;
  515. end;
  516. end;
  517. class function TObject.getinterfaceentry(const iid : tguid) : pinterfaceentry;
  518. var
  519. i: integer;
  520. intftable: pinterfacetable;
  521. Res: pinterfaceentry;
  522. begin
  523. getinterfaceentry:=nil;
  524. intftable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  525. if assigned(intftable) then begin
  526. i:=intftable^.EntryCount;
  527. Res:=@intftable^.Entries[0];
  528. while (i>0) and
  529. not (assigned(Res^.iid) and IsGUIDEqual(Res^.iid^,iid)) do begin
  530. inc(Res);
  531. dec(i);
  532. end;
  533. if (i>0) then
  534. getinterfaceentry:=Res;
  535. end;
  536. if (getinterfaceentry=nil)and not(classparent=nil) then
  537. getinterfaceentry:=classparent.getinterfaceentry(iid)
  538. end;
  539. class function TObject.getinterfaceentrybystr(const iidstr : string) : pinterfaceentry;
  540. var
  541. i: integer;
  542. intftable: pinterfacetable;
  543. Res: pinterfaceentry;
  544. begin
  545. getinterfaceentrybystr:=nil;
  546. intftable:=getinterfacetable;
  547. if assigned(intftable) then begin
  548. i:=intftable^.EntryCount;
  549. Res:=@intftable^.Entries[0];
  550. while (i>0) and (Res^.iidstr^<>iidstr) do begin
  551. inc(Res);
  552. dec(i);
  553. end;
  554. if (i>0) then
  555. getinterfaceentrybystr:=Res;
  556. end;
  557. if (getinterfaceentrybystr=nil)and not(classparent=nil) then
  558. getinterfaceentrybystr:=classparent.getinterfaceentrybystr(iidstr)
  559. end;
  560. class function TObject.getinterfacetable : pinterfacetable;
  561. begin
  562. getinterfacetable:=pinterfacetable((pointer(Self)+vmtIntfTable)^);
  563. end;
  564. {****************************************************************************
  565. TINTERFACEDOBJECT
  566. ****************************************************************************}
  567. function TInterfacedObject.QueryInterface(
  568. const iid : tguid;out obj) : longint;stdcall;
  569. begin
  570. if getinterface(iid,obj) then
  571. result:=0
  572. else
  573. result:=longint($80004002);
  574. end;
  575. function TInterfacedObject._AddRef : longint;stdcall;
  576. begin
  577. inclocked(frefcount);
  578. _addref:=frefcount;
  579. end;
  580. function TInterfacedObject._Release : longint;stdcall;
  581. begin
  582. if declocked(frefcount) then
  583. begin
  584. self.destroy;
  585. _Release:=0;
  586. end
  587. else
  588. _Release:=frefcount;
  589. end;
  590. procedure TInterfacedObject.AfterConstruction;
  591. begin
  592. { we need to fix the refcount we forced in newinstance }
  593. { further, it must be done in a thread safe way }
  594. declocked(frefcount);
  595. end;
  596. procedure TInterfacedObject.BeforeDestruction;
  597. begin
  598. if frefcount<>0 then
  599. HandleError(204);
  600. end;
  601. class function TInterfacedObject.NewInstance : TObject;
  602. begin
  603. NewInstance:=inherited NewInstance;
  604. TInterfacedObject(NewInstance).frefcount:=1;
  605. end;
  606. {****************************************************************************
  607. Exception Support
  608. ****************************************************************************}
  609. {$i except.inc}
  610. {****************************************************************************
  611. Initialize
  612. ****************************************************************************}