microsoft / cppwinrt

C++/WinRT
MIT License
1.61k stars 232 forks source link

Feature: Add support for agile+weak references #1389

Closed dmachaj closed 5 months ago

dmachaj commented 5 months ago

Version

2.0.230706.1

Summary

We have some STA-affine objects so we hand out winrt::agile_ref's to callers so that they can safely communicate with them from other threads. I am adding some cleanup code and I need to be able to cast these to IClosable and close them from a random MTA thread. The tricky part is that I need that cleanup code to hold weak references so I don't create a reference cycle and guarantee leaking of these objects.

cppwinrt has both weak_ref and agile_ref but they cannot be combined. This feature request is to add an agile_weak_ref struct that supports this.

Reproducible example

No response

Expected behavior

No response

Actual behavior

No response

Additional comments

@DefaultRyan had a code suggestion via email that I'm preserving here:

template <typename T>
struct agile_weak_ref
{
    agile_weak_ref(std::nullptr_t = nullptr) noexcept {}

    template<typename U = winrt::impl::com_ref<T> const&, typename = std::enable_if_t<std::is_convertible_v<U&&, winrt::impl::com_ref<T> const&>>>
    agile_weak_ref(U&& object)
    {
        winrt::weak_ref<T> weakRef{ std::forward<U>(object) };
        m_ref = winrt::make_agile(*reinterpret_cast<winrt::com_ptr<winrt::impl::IWeakReference>*>(&weakRef));
    }

    [[nodiscard]] auto get() const noexcept
    {
        decltype(std::declval<winrt::weak_ref<T>>().get()) result;
        if (m_ref)
        {
          auto temp = m_ref.get();
          if (temp)
          {
            result = reinterpret_cast<winrt::weak_ref<T>*>(&temp)->get();
          }
        }
        return result;
    }

    explicit operator bool() const noexcept
    {
      return static_cast<bool>(m_ref);
    }

private:
    winrt::agile_ref<winrt::impl::IWeakReference> m_ref;
};
github-actions[bot] commented 5 months ago

This issue is stale because it has been open 10 days with no activity. Remove stale label or comment or this will be closed in 5 days.