2

Is TInterfacedObject._Release and TInterfacedObject._AddRef thread safe? I can see FRefCount is thread safe, but Destroy is not protected by locks or something else.

function TInterfacedObject._Release: Integer;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then
    Destroy;
end;

Could different thread execute Destroy at the same time causing a race condition?

qgi
  • 25
  • 4
  • 1
    The whole point is that you don't call destroy because you work with the interface rather than the object. – David Heffernan Aug 23 '23 at 14:51
  • I know that I cannot call Destroy directly. If one thread checking Result is 0 and try to free, while another thread add ref? Could it happen? – qgi Aug 23 '23 at 14:54
  • 2
    If result reaches zero then nothing can have a reference any more – David Heffernan Aug 23 '23 at 15:02
  • Even in multi-thread environment? – qgi Aug 23 '23 at 16:38
  • 1
    @qgi yes, even in multi-thread. If the refcount falls to 0, it means there are NO REFERENCES WHATSOEVER to the object. If a thread is trying to increment the refcount, there must have been an existing reference to the object to begin with, so the refcount should not fall to 0 while the thread is incrementing the refcount. Unless you are doing something unusual, like passing around references without refcounting them – Remy Lebeau Aug 23 '23 at 16:40

1 Answers1

4

Implementation of reference counting methods in TInterfacedObject is thread safe as reference count is incremented and decremented atomically.

When reference count of object instance reaches zero in _Release method, that means there is no longer any other strong reference to that object and destroying the object will be thread-safe.

Similarly when you look at _AddRef method, when you already have a strong reference to an object, taking another strong reference from it will also be thread-safe.

However, that is not the whole story and there are other things that need to be taken in consideration when handling reference counted instances across multiple threads.

  • reference assignment is not thread-safe - you cannot have a variable and write to it from multiple threads in thread-safe manner without using additional access protection mechanisms that will ensure only single thread has access to that reference at a time, like locks.

  • taking strong reference from weak reference is not thread-safe - if thread only has a weak reference to some reference counted instance then you cannot assign that weak reference to a strong one in thread-safe manner

Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159