Circular reference issue of IInterface Object
" class="oa" bg nowrap="nowrap" width="1%">Joanna Carter (TeamB) | Jun 13 2004, 2:50 pm show options |
Newsgroups: borland.public.delphi.oodesign |
From: "Joanna Carter \(TeamB\)" |
Date: Sun, 13 Jun 2004 19:50:12 +0100 |
Local: Sun,Jun 13 2004 2:50 pm |
Subject: Re: Interfaces - Usage rules |
Reply to Author | Forward | Print | Individual Message | Show original | Report Abuse |
"Robert MIRCEA"
40cc1...@newsgroups.borland.co
mix
> the two of them"
use
> interfaces. How about some rules regarding the inter-referencing of
> interfaces/objects?
to the mutual reference, neither object can be the first to release the
other's memory, therefore you have a memory leak. However, if you use a week
reference on one of the objects, usually the inner, then the problem goes
away.
IInner = interface
end;
IOuter = interface
end;
TInner = class(TInterfacedObject, IInner)
private
fOuter: Pointer; // weak reference
protected
function GetOuter: IOuter; // access function
public
constructor Create(const Outer: IOuter);
end;
constructor TInner.Create(const Outer: IOuter);
begin
inherited Create;
fOuter := Pointer(Outer); // does not increment refcount on Outer
end;
function TInner.GetOuter: IOuter;
begin
Result := IOuter(fOuter); // increments refcount until caller either
// nils result or it goes out of
scope
end;
TOuter = class(TInterfacedObject, IOuter)
private
fInner: IInner; // normal reference
end;
> need to hold a list of interfaces. After studying the code for this class,
> I've noticed that TInterfaceList uses internally a TThreadList. However,
it
> seems to me that iterating thru a TInterfaceList using Items property
might
> be subject of heavy locking/unlocking of the underlying list.
go. Unless you fancy doing it yourself, just use it :-) Any penalties for
locks don't seem to be significant on most modern processors.
> operation, how would you interate efficiently thru a TInterfaceList?
I have never had any problems and certainly don't notice any untoward side
effects.
parameter
> for a method? What is the difference between passing an interface with
> "const" and without "const"?
extraneous _AddRef and _Release calls that would otherwise be generated on
entry and exit (this is the same as for strings). As a rule, always use
const.
Also if you are passing a newly created interface ref object into a const
param, then ensure that you cast the constructor call to the desired
interface otherwise the end of the method that creates the temporary object
will release the memory and you will get an AV.
procedure TestMethodToCall(const Thing: IThing);
begin
end;
procedure TTest.ExecuteBadly;
begin
TestMethodToCall(TThing.Create
end; // temporary object released here
procedure TTest.ExecuteProperly;
begin
TestMethodToCall(TThing.Create as IThing);
end;
Joanna
--
Joanna Carter (TeamB)
Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker
In article <40cc1...@newsgroups.borland.c > Hi everybody, Hi Robert :)> I am seeking some advice from some more experienced users of Delphi That's a very good rule of thumb. You -can- break the rule if you> interfaces regarding the rules I should follow whenever I develop my domain > objects with the use of interfaces. I am aware of only one rule: > "Either always use interface references, or object references, but never mix > the two of them" understand exactly what's going on, but by and large it's a bad idea. -- 8< -- Here's a quick breakdown of why: * Using interface references inserts (Object)._AddRef calls during * Using interface references inserts (Object)._Release calls during re- * If you assign the result of a constructor to an object reference (X : -- 8< -- I just ran into some the other day where I *had* to make a TComponent > and I would like to know more code patterns that I should follow when I use Here are a few 'rules' I go by when using interfaces:> interfaces. How about some rules regarding the inter-referencing of > interfaces/objects? * Keep the interfaces as technology-independent as possible (so, for (ideally, you should be able to completely fake the object behind your * Put the technology-dependent items into the constructor if possible (so * Make your interfaces cohesive. If you have an object that needs to do As for inter-referencing, that's always a tough question. It's always Essentially, anywhere you may have circular references, you have two * Make all back-references 'weak' (i.e. non-reference-counted) - * Don't just let go of the references or let them go out of scope - tell There are a lot of variations on that last theme. A simple means might be Make an interface: IBye = interface Make a Bye() procedure like this: procedure Bye(var AInterface); Add IBye to any object that refers back to its parent. Implement it by type procedure TMyObject.Goodbye; > Second question: > I've noticed that TInterfaceList is the "recommended" way to go whenever I > need to hold a list of interfaces. After studying the code for this class, > I've noticed that TInterfaceList uses internally a TThreadList. However, it > seems to me that iterating thru a TInterfaceList using Items property might > be subject of heavy locking/unlocking of the underlying list. > Since using critical sections for synchronization is a very expensive > operation, how would you interate efficiently thru a TInterfaceList? by and large, a complete myth; it doesn't even rank up there with adding two strings together :) They're not interrupts, and they don't do anything funny to the processor - you'd be surprised how mundane they are beneath the radar. The actual expensive part of the critical section is the You only get the WaitForSingleObject happening if you try to Acquire the You honestly won't notice. A profiler will prove it as well ;) That said, remember to use it as an IInterfaceList: var ...and you can create a non-critical-section-based list yourself later, > Third question: (1)> What is the inner mechanism when passing an interface as a "const" parameter > for a method? What is the difference between passing an interface with > "const" and without "const"? procedure A(const X: IMyInterface); begin ... end; (2) The non-const (2) is exactly like the const (1) with a couple of There's an X._AddRef during the call to A in (2). By and large, you can use const to not bother with those two calls. And, of course, as with other 'const' versus 'non-const' parameters, you There are a couple of presentations I put together that you can add to My apologies in advance for my tendency towards information overload. > Thank you, I hope it helps, Robert!> Robert -- Ritchie AnnandSenior Software Architect Malibu Engineering & Software Ltd. http://www.malibugroup.com http://www.nimblebrain.net |
0 Comments:
Post a Comment
<< Home