http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1312
В процессе обсуждения, как мне кажется, родилось решение, которое может быть использовано для своих классов, которые должны реализовать интерфейс, однако управление временем жизни объектов должно быть ручное. Вот класс, от которого в таком случае можно унаследоваться:
TMyInterfacedObject = class(TObject, IInterface)
protected
FRefCount: Integer;
FDestroyed: Boolean;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
procedure FreeInstance; override;
end;
procedure TMyInterfacedObject.FreeInstance;
begin
FDestroyed := True;
if RefCount = 0 then
inherited FreeInstance;
end;
function TMyInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
function TMyInterfacedObject._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;
function TMyInterfacedObject._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if (Result = 0) and FDestroyed then
FreeInstance;
end;
При вызове Free для таких объектов освобождение памяти под экземпляр произойдет только в том случае, если равен нулю счетчик ссылок. Иначе - просто будет выполнен код деструктора, а освобождение памяти произойдет только после обнуления счетчика. С другой стороны, обнуление счетчика не приведет к уничтожению экземпляра до тех пор, пока явно не вызвать для данного объекта Free.
5 comments:
Ins, для оформления кода подходит тэг blockquote (в угловых скобках) или кнопка "цитата".
Просто сейчас твой код выглядит нечитабельно :(
Спасибо! Пошаманил с тегами, стало немного лучше :)
Кстати, вот соответствующий баг-репорт в QC: http://qc.codegear.com/wc/qcmain.aspx?d=9157
Интересный пост:
http://blogs.teamb.com/craigstuntz/2008/01/23/37786
Пост действительно интересный, анализ проведен хороший. Ясно то, что проблема существует, но не ясно, как ее лучше решить. Однако лично мне наименьшим из всех зол кажется вариант "The compiler could insert calls to _AddRef and _Release for a reference of an interface type which is a subtype of IUnknown, and not insert these calls for a reference of an interface type which is not a subtype of IUnknown", даже не смотря на проблемы, которые он влечет за собой. В конце концов, в этом случае ответственность скорее будет лежать на программисте, в данном же случае имеет место быть самый настоящий косяк.
Post a Comment