Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion strings/base_abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ namespace winrt::impl
virtual int32_t __stdcall unused2() noexcept = 0;
virtual int32_t __stdcall unused3() noexcept = 0;
virtual int32_t __stdcall Insert(void*, void*, bool*) noexcept = 0;
virtual int32_t __stdcall Remove(void*) noexcept = 0;
virtual int32_t __stdcall unused4() noexcept = 0;
virtual int32_t __stdcall unused5() noexcept = 0;
};

struct __declspec(novtable) IWeakReference : unknown_abi
Expand Down
23 changes: 19 additions & 4 deletions strings/base_implements.h
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,14 @@ namespace winrt::impl
};
#endif

inline com_ptr<IStaticLifetimeCollection> get_static_lifetime_map()
{
auto const lifetime_factory = get_activation_factory<impl::IStaticLifetime>(L"Windows.ApplicationModel.Core.CoreApplication");
Windows::Foundation::IUnknown collection;
check_hresult(lifetime_factory->GetCollection(put_abi(collection)));
return collection.as<IStaticLifetimeCollection>();
}

template <typename D>
auto make_factory() -> typename impl::implements_default_interface<D>::type
{
Expand All @@ -1209,10 +1217,7 @@ namespace winrt::impl
}
else
{
auto const lifetime_factory = get_activation_factory<impl::IStaticLifetime>(L"Windows.ApplicationModel.Core.CoreApplication");
Windows::Foundation::IUnknown collection;
check_hresult(lifetime_factory->GetCollection(put_abi(collection)));
auto const map = collection.as<IStaticLifetimeCollection>();
auto const map = get_static_lifetime_map();
param::hstring const name{ name_of<typename D::instance_type>() };
void* result{};
map->Lookup(get_abi(name), &result);
Expand Down Expand Up @@ -1304,6 +1309,16 @@ WINRT_EXPORT namespace winrt
}
}

template <typename... FactoryClasses>
inline void clear_factory_static_lifetime()
{
auto unregister = [map = impl::get_static_lifetime_map()](param::hstring name)
{
map->Remove(get_abi(name));
};
((unregister(name_of<typename FactoryClasses::instance_type>())), ...);
}

template <typename D, typename... I>
struct implements : impl::producers<D, I...>, impl::base_implements<D, I...>::type
{
Expand Down
42 changes: 34 additions & 8 deletions test/old_tests/Component/Events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,25 +74,51 @@ namespace winrt::Component::factory_implementation

bool Events::TestStaticLifetime()
{
auto GetReferenceCount = [this]()
{
AddRef();
return Release();
};

// Capture current reference count.
AddRef();
auto refcount = Release();
auto refcount = GetReferenceCount();

// Reset constructor count.
s_constructorCount = 0;

auto self = make_self<Events>();
if (self.get() != this)
// make_self should return a reference to ourselves
// since we are static_lifetime.
if (make_self<Events>().get() != this)
{
return false;
}
self = nullptr;

// Refcount should be unchanged.
if (refcount != GetReferenceCount())
{
return false;
}

// Should not have been constructed spuriously.
AddRef();
auto new_refcount = Release();
if (s_constructorCount != 0)
{
return false;
}

// Clear the static lifetime. That should drop the reference count.
clear_factory_static_lifetime<Events>();
if (refcount == GetReferenceCount())
{
return false;
}

// Making a new object should put a different instance into
// the static lifetime.
if (make_self<Events>().get() == this)
{
return false;
}

return refcount == new_refcount && s_constructorCount == 0;
return true;
}
}