Skip to content

Commit 386cd60

Browse files
authored
Allow empty apartment_contexts (#861)
1 parent dead82f commit 386cd60

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

strings/base_coroutine_threadpool.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,23 @@ namespace winrt::impl
5050

5151
struct resume_apartment_context
5252
{
53+
resume_apartment_context() = default;
54+
resume_apartment_context(std::nullptr_t) : m_context(nullptr), m_context_type(-1) {}
55+
resume_apartment_context(resume_apartment_context const&) = default;
56+
resume_apartment_context(resume_apartment_context&& other) noexcept :
57+
m_context(std::move(other.m_context)), m_context_type(std::exchange(other.m_context_type, -1)) {}
58+
resume_apartment_context& operator=(resume_apartment_context const&) = default;
59+
resume_apartment_context& operator=(resume_apartment_context&& other) noexcept
60+
{
61+
m_context = std::move(other.m_context);
62+
m_context_type = std::exchange(other.m_context_type, -1);
63+
return *this;
64+
}
65+
bool valid() const noexcept
66+
{
67+
return m_context_type >= 0;
68+
}
69+
5370
com_ptr<IContextCallback> m_context = try_capture<IContextCallback>(WINRT_IMPL_CoGetObjectContext);
5471
int32_t m_context_type = get_apartment_type().first;
5572
};
@@ -88,6 +105,7 @@ namespace winrt::impl
88105

89106
inline auto resume_apartment(resume_apartment_context const& context, coroutine_handle<> handle)
90107
{
108+
WINRT_ASSERT(context.valid());
91109
if ((context.m_context == nullptr) || (context.m_context == try_capture<IContextCallback>(WINRT_IMPL_CoGetObjectContext)))
92110
{
93111
handle();
@@ -338,6 +356,12 @@ WINRT_EXPORT namespace winrt
338356

339357
struct apartment_context
340358
{
359+
apartment_context() = default;
360+
apartment_context(std::nullptr_t) : context(nullptr) { }
361+
362+
operator bool() const noexcept { return context.valid(); }
363+
bool operator!() const noexcept { return !context.valid(); }
364+
341365
bool await_ready() const noexcept
342366
{
343367
return false;

test/old_tests/UnitTests/apartment_context.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,37 @@ namespace
1111
IAsyncAction Async()
1212
{
1313
apartment_context context;
14+
REQUIRE(context);
15+
16+
// Verify basic operations.
17+
18+
// copyable - verify source is still good after copy
19+
apartment_context context2(context);
20+
REQUIRE(context);
21+
22+
// movable - verify source is empty after move
23+
apartment_context context3(std::move(context));
24+
REQUIRE(!context);
25+
26+
// copy-assignable - verify source is still good
27+
context = context2;
28+
REQUIRE(context2);
29+
30+
// move-assignable - verify source is empty after move
31+
context = std::move(context3);
32+
REQUIRE(!context3);
33+
34+
// emptyable
35+
context2 = nullptr;
36+
REQUIRE(!context2);
37+
38+
// Self-copy-assignment
39+
context = context;
40+
REQUIRE(context);
41+
42+
// Self-move-assignment
43+
context = std::move(context);
44+
REQUIRE(context);
1445

1546
co_await context;
1647
}
@@ -30,11 +61,12 @@ namespace
3061

3162
auto get_winrt_apartment_context_for_com_context(com_ptr<::IContextCallback> const& com_context)
3263
{
33-
std::optional<decltype(apartment_context())> context;
64+
apartment_context context{ nullptr };
65+
REQUIRE(!context); // constructed empty
3466
InvokeInContext(com_context.get(), [&] {
3567
context = apartment_context();
3668
});
37-
return context.value();
69+
return context;
3870
}
3971

4072
bool is_nta_on_mta()

0 commit comments

Comments
 (0)