omni::core::WeakPtr

Defined in omni/core/IWeakObject.h

template<typename T>
class WeakPtr

Weak pointer to ONI objects much like std::weak_ptr.

The IWeakObject interface support the notion of “weak pointers”. Unlike “strong pointers” (e.g. ObjectPtr) weak pointers do not affect the pointee’s reference count. While this sounds like a raw pointer (and possibly a bad idea), the magic of a weak pointer is that if the pointee’s reference count goes to zero, the weak pointer updates its internal pointer to nullptr.

Below are several practical use cases of weak pointers.

Breaking Reference Count Cycles

A reference count cycle happens when an object “A” contains an ObjectPtr to object “B”. At this same time, object “B” holds an ObjectPtr to object “A”. Since each object increments the other’s reference count, neither is every destructed. To break this cycle, one of the objects can hold a WeakPtr to the other object.

Pointing to Objects Whose Code May Be Unloaded From Memory

Carbonite supports the notion of plugins that can be loaded, unloaded, and reloaded at runtime. Often code from DLL X holds an ObjectPtr to code from DLL Y. If the user unloads Y, and DLL X still wishes to use Y, the application is likely to crash when DLL X attempts to access the unloaded code.

Instead of storing an ObjectPtr, a WeakPtr can be used instead. When DLL X wants to access the code in DLL Y, WeakPtr::getObjectPtr() is called, which converts the WeakPtr into an ObjectPtr. Here, if the underlying object’s strong reference count is zero, the returned ObjectPtr will point to nullptr. DLL X simply must check if the ObjectPtr points to nullptr before using the pointer.

Above, we make the assumption that DLL Y will either:

  • Refuse to unload as long as an object it produced has a non-zero strong reference count.

  • Will cleanup all external ObjectPtr objects that hold a reference to an object produced by the DLL. One way to implement this is for the plugin to allow callbacks to be registered with it that will be invoked when the DLL is about to unloaded.

Usage

Weak pointers should be used as follows:

    // the signature of getWeakExample is:
    //
    //   ObjectPtr<IWeakExample> getWeakExample();
    WeakPtr<IWeakExample> weakPtr{ getWeakExample() };

    // <insert other interesting code here>

    // to access the object, the WeakPtr must be converted to an ObjectPtr
    ObjectPtr<IWeakExample> strongPtr{ weakPtr.getObjectPtr() };

    // since the weak pointer doesn't increment the reference count of the object, the object may have been destroyed.
    // if so, nullptr is returned.
    if (strongPtr)
    {
        strongPtr->doFoo();
    }

Public Functions

inline WeakPtr(std::nullptr_t = nullptr) noexcept

Allow implicit conversion from nullptr to an WeakPtr.

inline WeakPtr(const omni::core::ObjectPtr<T> &strong) noexcept

Strong pointer to weak pointer conversion.

inline WeakPtr(T *strong) noexcept

Raw pointer to weak pointer conversion.

WeakPtr(const WeakPtr &other) noexcept = default

Copy constructor.

WeakPtr(WeakPtr &&other) noexcept = default

Move constructor.

~WeakPtr() noexcept = default
WeakPtr &operator=(const WeakPtr &other) noexcept = default

Assignment operator.

Thread Safety

This method is not thread safe.

WeakPtr &operator=(WeakPtr &&other) noexcept = default

Move assignment operator.

Thread Safety

This method is not thread safe.

inline omni::core::ObjectPtr<T> getObjectPtr() const noexcept

Returns an omni::core::ObjectPtr to the object to which this weak pointer is pointing.

The returned object will point to nullptr if there are no “strong” references to the underlying object. Otherwise, if a non-nullptr pointer is returned, the object will live at least as long as the returned omni::core::ObjectPtr.

To understand how/when to use weak pointers and this method, consult the class documentation for omni::core::WeakPtr.

Equivalent to WeakPtr::lock().

Thread Safety

This method is not thread safe.

inline omni::core::ObjectPtr<T> lock() const noexcept

Returns an omni::core::ObjectPtr to the object to which this weak pointer is pointing.

The returned object will point to nullptr if there are no “strong” references to the underlying object. Otherwise, if a non-nullptr pointer is returned, the object will live at least as long as the returned omni::core::ObjectPtr.

To understand how/when to use weak pointers and this method, consult the class documentation for omni::core::WeakPtr.

Equivalent to WeakPtr::getObjectPtr().

Thread Safety

This method is not thread safe.