Posts

Showing posts with the label Weak

Zeroing Weak Object References

In the two-part post series, The purpose of weak references - Part I and The purpose of weak references - Part II , I wrote about the purpose of weak references in automatic reference counting, as well as in manual memory management, where they are commonly referred to as non-owning references. In ARC, object references to reference-counted objects are unsafe, non-zeroing weak references, and in manual memory management, non-owning references to an object instance are also unsafe. Unsafe, in the above context, means that you can safely use such references only if the object instance they point to always has a longer lifetime than the unsafe reference, or that there is additional mechanism (code) that will notify you when the object is destroyed, so you know the reference is not pointing to a valid object anymore. In manual memory management, TComponent implements such a notification mechanism. However, there are two downsides: first, it only works with TComponent descendants; and...

The purpose of weak references - Part II

Image
In the first part of this post series, I covered owning and non-owning references under manual memory management, and the purpose of non-owning (weak) references in that memory model. Following the same use cases, we can now clearly show the purpose of their counterparts under the automatic reference counting memory model. Automatic reference counting Automatic reference counting is a memory model under which an object instance will be valid as long as there is at least one strong reference to that object instance. When the last strong reference goes out of scope or is nilled, the object's reference count will drop to zero, and the instance will be automatically destroyed. One of the side-effects of that design is that two object instances that are no longer reachable through any outside references can hold strong references to each other, thus keeping themselves alive and creating memory leaks. This is called a reference cycle. To prevent problems with reference cycles, ARC h...

The purpose of weak references - Part I

Image
The terminology "weak and strong references" is commonly used in the context of automatic reference counting. In the context of manual memory management, we talk about ownership, and owning and non-owning references. While the terminology is different, those two different kinds of references represent the same concept, regardless of the underlying memory management model. Strong references are the equivalent of owning references, and weak references are the equivalent of non-owning references. Understanding those relations can help us understand the purpose of weak references in automatic reference counting, and instead of thinking about them merely in the context of breaking reference cycles, we should think about them as non-owning references—in other words, additional references to an object instance that don't participate in its memory management, and could be invalidated after the object is released through other code and owning references. Because non-owning (wea...

Optimizing ARC - weakness of [weak]

In Delphi, the [weak] attribute is used to break strong reference cycles between reference counted object instances. It can be used with the ARC compiler on both object and interface references, and with the classic compiler for interface references. Weak interface references were introduced in Delphi 10.1 Berlin. Now, there is a teeny-weeny problem with the [weak] attribute. It denotes a zeroing weak reference that will be zeroed (niled) when the object it points to is no longer valid. In order to do that, the compiler has to track such objects at runtime and that introduces some overhead. If you are tracking many such references, that can introduce a significant performance loss. Not all weak references that serve the purpose of breaking reference cycles need to be zeroed out. If you can guarantee that a [weak] reference will never outlive the object it points to, all that tracking and zeroing is useless. To avoid a performance penalty in such cases, you can use the [unsafe] ...