Closed gotow closed 5 years ago
While
dealloc
is guaranteed to not execute concurrently with other instance methods
Right, so the lock shouldn't be needed.
for this code to run correctly there must be a memory barrier before the
dealloc
that ensures that changes to these fields are visible to other cores.
I don't follow this
Sorry Matt. After testing again with the thread sanitizer turned on, I can't reproduce the original problem. I'll go back and see if I can figure out how I was generating the errors in the first place (they definitely happened - I even re-checked before submitting my pull request). I agree - the lock shouldn't be needed, but I was getting errors without it. Now I'm not sure why :-/
@mdiep it's incorrect to access a shared variable that is being read and written from multiple threads without any memory synchronization mechanism. In this case, a shared variable is being accessed while a lock is being held, but in the dealloc
it is accessed without holding the lock.
While this seems like something that should work, as the unprotected access happens on a single thread after the potential writes caused by the instance methods, instruction reordering (which is done by the compiler) and memory reordering (which is done in the CPU) may affect the order that updates to this variable are seen to other threads in the system.
So although instruction reordering is probably irrelevant here, as ObjC is a dynamic language and the compiler cannot reorder instructions between two instance methods, memory reordering is something that can happen as long as there's something that triggers a memory barrier before -dealloc
is called.
The
_mutex
protects_inlineDisposables
and_disposables
. Whiledealloc
is guaranteed to not execute concurrently with other instance methods, for this code to run correctly there must be a memory barrier before thedealloc
that ensures that changes to these fields are visible to other cores. Although there's probably some kind of an (implicit?) memory barrier, TSan may complain as these fields are being accessed without_mutex
being held.Note that I'd be very careful to add a mutex here as it may dramatically affect the performance of RAC since in a common usage of this framework
RACCompoundDisposable
objects are created and destroyed in masses.