Skip to content

Commit 2ee9368

Browse files
committed
change out async to a new name, with it being true by default.
add new unittest to test nullable lookup.
1 parent 18a57a8 commit 2ee9368

File tree

7 files changed

+75
-20
lines changed

7 files changed

+75
-20
lines changed

.runsettings

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
<ExecutionMode>Single</ExecutionMode>
1414
<FilenameFilter>(?i:Test)</FilenameFilter><!-- Regex filter -->
1515
<ForceListContent>true</ForceListContent>
16-
<CombinedTimeout>30000</CombinedTimeout><!-- 30s in Milliseconds -->
1716
<DebugBreak>on</DebugBreak>
1817
<IncludeHidden>true</IncludeHidden>
1918
<Logging>Verbose</Logging>

cppwinrt/code_writers.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1881,7 +1881,7 @@ namespace cppwinrt
18811881
upcall,
18821882
bind<write_produce_args>(method_signature));
18831883
w.write(R"(
1884-
if (out_param_val)
1884+
if (out_param_val.has_value())
18851885
{
18861886
*% = detach_from<%>(std::move(*out_param_val));
18871887
}
@@ -1934,6 +1934,7 @@ namespace cppwinrt
19341934
std::string upcall = "this->shim().";
19351935
auto name = get_name(method);
19361936
upcall += name;
1937+
// if (type_name == "Windows.Foundation.Collections.IMapView`2")
19371938
if (name == "Lookup")
19381939
{
19391940
// Special-case Lookup to look for a TryLookup here, to avoid a throw/originate

strings/base_coroutine_foundation.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -351,9 +351,9 @@ namespace winrt::impl
351351
return m_promise->enable_cancellation_propagation(value);
352352
}
353353

354-
bool avoid_cancel_origination(bool value = true) const noexcept
354+
bool originate_on_cancel(bool value = true) const noexcept
355355
{
356-
return m_promise->enable_avoid_cancel_origination(value);
356+
return m_promise->originate_on_cancel(value);
357357
}
358358
private:
359359

@@ -488,13 +488,13 @@ namespace winrt::impl
488488
if (m_status.load(std::memory_order_relaxed) == AsyncStatus::Started)
489489
{
490490
m_status.store(AsyncStatus::Canceled, std::memory_order_relaxed);
491-
if (cancellable_promise::avoid_cancel_origination_enabled())
491+
if (cancellable_promise::originate_on_cancel())
492492
{
493-
m_exception = std::make_exception_ptr(hresult_canceled(hresult_error::avoid_originate));
493+
m_exception = std::make_exception_ptr(hresult_canceled());
494494
}
495495
else
496496
{
497-
m_exception = std::make_exception_ptr(hresult_canceled());
497+
m_exception = std::make_exception_ptr(hresult_canceled(hresult_error::no_originate));
498498
}
499499
cancel = std::move(m_cancel);
500500
}
@@ -639,13 +639,13 @@ namespace winrt::impl
639639
{
640640
if (Status() == AsyncStatus::Canceled)
641641
{
642-
if (cancellable_promise::avoid_cancel_origination_enabled())
642+
if (cancellable_promise::originate_on_cancel())
643643
{
644-
throw winrt::hresult_canceled(hresult_error::avoid_originate);
644+
throw winrt::hresult_canceled();
645645
}
646646
else
647647
{
648-
throw winrt::hresult_canceled();
648+
throw winrt::hresult_canceled(hresult_error::no_originate);
649649
}
650650
}
651651

strings/base_coroutine_threadpool.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,14 @@ WINRT_EXPORT namespace winrt
180180
return m_propagate_cancellation;
181181
}
182182

183-
bool enable_avoid_cancel_origination(bool value) noexcept
183+
bool originate_on_cancel(bool value = true) noexcept
184184
{
185-
return std::exchange(m_avoid_cancel_origination, value);
185+
return std::exchange(m_originate_on_cancel, value);
186186
}
187187

188-
bool avoid_cancel_origination_enabled() const noexcept
188+
bool should_originate_on_cancel() const noexcept
189189
{
190-
return m_avoid_cancel_origination;
190+
return m_originate_on_cancel;
191191
}
192192

193193
private:
@@ -196,7 +196,7 @@ WINRT_EXPORT namespace winrt
196196
std::atomic<canceller_t> m_canceller{ nullptr };
197197
void* m_context{ nullptr };
198198
bool m_propagate_cancellation{ false };
199-
bool m_avoid_cancel_origination{ false };
199+
bool m_originate_on_cancel{ true }; // By default, will call RoOriginateError before throwing a cancel error code.
200200
};
201201

202202
template <typename Derived>

strings/base_error.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ WINRT_EXPORT namespace winrt
8484
{
8585
struct hresult_error
8686
{
87-
struct avoid_originate_t {};
88-
static constexpr avoid_originate_t avoid_originate{};
87+
struct no_originate_t {};
88+
static constexpr no_originate_t no_originate{};
8989

9090
using from_abi_t = take_ownership_from_abi_t;
9191
static constexpr auto from_abi{ take_ownership_from_abi };
@@ -112,7 +112,7 @@ WINRT_EXPORT namespace winrt
112112
originate(code, nullptr, sourceInformation);
113113
}
114114

115-
explicit hresult_error(hresult const code, avoid_originate_t, [[maybe_unused]] winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code))
115+
explicit hresult_error(hresult const code, no_originate_t, [[maybe_unused]] winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code))
116116
{
117117
}
118118

@@ -332,7 +332,7 @@ WINRT_EXPORT namespace winrt
332332
struct hresult_canceled : hresult_error
333333
{
334334
hresult_canceled(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, sourceInformation) {}
335-
hresult_canceled(hresult_error::avoid_originate_t) noexcept : hresult_error(impl::error_canceled, hresult_error::avoid_originate) {}
335+
hresult_canceled(hresult_error::no_originate_t) noexcept : hresult_error(impl::error_canceled, hresult_error::no_originate) {}
336336
hresult_canceled(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, message, sourceInformation) {}
337337
hresult_canceled(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi, sourceInformation) {}
338338
};

test/old_tests/UnitTests/TryLookup.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,58 @@ TEST_CASE("trylookup_from_abi specialization")
188188
// regular lookup should throw the same error
189189
REQUIRE_THROWS_AS(map.Lookup(123), hresult_wrong_thread);
190190
}
191+
192+
TEST_CASE("trylookup_from_abi specialization with IInspectable")
193+
{
194+
// A map that throws a specific error, used to verify various edge cases.
195+
// and implements tryLookup, to take advantage of an optimization to avoid a throw.
196+
struct map_with_try_lookup : implements<map_with_try_lookup, IMapView<int, IInspectable>>
197+
{
198+
hresult codeToThrow{ S_OK };
199+
bool shouldThrowOnTryLookup{ false };
200+
bool returnNullptr{ false };
201+
std::optional<IInspectable> TryLookup(int, trylookup_from_abi_t)
202+
{
203+
if (returnNullptr)
204+
{
205+
return { nullptr };
206+
}
207+
else if (shouldThrowOnTryLookup)
208+
{
209+
throw_hresult(codeToThrow);
210+
}
211+
else
212+
{
213+
return { std::nullopt };
214+
}
215+
}
216+
IInspectable Lookup(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test
217+
int32_t Size() { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test
218+
bool HasKey(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test
219+
void Split(IMapView<int, IInspectable>&, IMapView<int, IInspectable>&) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test
220+
};
221+
222+
auto self = make_self<map_with_try_lookup>();
223+
IMapView<int, IInspectable> map = *self;
224+
225+
// Ensure that we return a value on nullptr, a nullptr is a valid IInspectable in the Map
226+
self->returnNullptr = true;
227+
REQUIRE(map.TryLookup(123) == IInspectable{nullptr});
228+
REQUIRE(map.Lookup(123) == IInspectable{nullptr});
229+
230+
// Make sure that we use the TryLookup specialization, and don't throw an unexpected exception.
231+
self->shouldThrowOnTryLookup = false;
232+
self->returnNullptr = false;
233+
REQUIRE(map.TryLookup(123) == IInspectable{nullptr});
234+
// make sure regular lookup stll throws bounds
235+
REQUIRE_THROWS_AS(map.Lookup(123), hresult_out_of_bounds);
236+
237+
// Simulate a non-agile map that is being accessed from the wrong thread.
238+
// "Try" operations should throw rather than erroneously report "not found".
239+
// Because they didn't even try. The operation never got off the ground.
240+
self->shouldThrowOnTryLookup = true;
241+
self->codeToThrow = RPC_E_WRONG_THREAD;
242+
REQUIRE_THROWS_AS(map.TryLookup(123), hresult_wrong_thread);
243+
// regular lookup should throw the same error
244+
REQUIRE_THROWS_AS(map.Lookup(123), hresult_wrong_thread);
245+
}

test/test/async_check_cancel.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ namespace
133133
winrt_throw_hresult_handler = exceptionLogger;
134134

135135
auto cancel = co_await get_cancellation_token();
136-
cancel.avoid_cancel_origination(true);
136+
cancel.originate_on_cancel(false);
137137

138138
co_await resume_on_signal(event);
139139

0 commit comments

Comments
 (0)