Skip to content

Commit 4196e08

Browse files
jonwiskennykerrJon Wiswall
authored
Increase foldability of various templates (#1338)
* Add SDKReference-sourced WinMDs when building * Add solution items so they're more easily edited * Update development guidance slightly * First attempt at template folding * Make packages easier to build, remove warning about unreferenced static * Lift delegate creation out for better folding * More folding of events * Another delegate folded * PR feedback * Speculative improvement for QueryInterface * PR feedback --------- Co-authored-by: Jon Wiswall <[email protected]> Co-authored-by: Kenny Kerr <[email protected]> Co-authored-by: Jon Wiswall <[email protected]>
1 parent 0958cf3 commit 4196e08

File tree

7 files changed

+128
-90
lines changed

7 files changed

+128
-90
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ C++/WinRT is an entirely standard C++ language projection for Windows Runtime (W
1111

1212
Don't build C++/WinRT yourself - just download the latest version here: https://aka.ms/cppwinrt/nuget
1313

14+
## Working on the compiler
15+
1416
If you really want to build it yourself, the simplest way to do so is to run the `build_test_all.cmd` script in the root directory. Developers needing to work on the C++/WinRT compiler itself should go through the following steps to arrive at an efficient inner loop:
1517

1618
* Open a dev command prompt pointing at the root of the repo.
1719
* Open the `cppwinrt.sln` solution.
18-
* Build the x64 Release configuration of the `cppwinrt` project only. Do not attempt to build anything else just yet.
20+
* Rebuild the x64 Release configuration of the `cppwinrt` project only. Do not attempt to build anything else just yet.
1921
* Run `build_projection.cmd` in the dev command prompt.
2022
* Switch to the x64 Debug configuration in Visual Studio and build all projects as needed.
2123

build_nuget.cmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
rem @echo off
22

33
set target_version=%1
4-
if "%target_version%"=="" set target_version=1.2.3.4
4+
if "%target_version%"=="" set target_version=3.0.0.0
55

66
call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd
77
call msbuild /m /p:Configuration=Release,Platform=x64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd
@@ -10,4 +10,4 @@ call msbuild /m /p:Configuration=Release,Platform=arm64,CppWinRTBuildVersion=%ta
1010

1111
call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:cppwinrt
1212

13-
nuget pack nuget\Microsoft.Windows.CppWinRT.nuspec -Properties cppwinrt_exe=%cd%\_build\x86\Release\cppwinrt.exe;cppwinrt_fast_fwd_x86=%cd%\_build\x86\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%cd%\_build\x64\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%cd%\_build\arm\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%cd%\_build\arm64\Release\cppwinrt_fast_forwarder.lib
13+
nuget pack nuget\Microsoft.Windows.CppWinRT.nuspec -Properties target_version=%target_version%;cppwinrt_exe=%cd%\_build\x86\Release\cppwinrt.exe;cppwinrt_fast_fwd_x86=%cd%\_build\x86\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%cd%\_build\x64\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%cd%\_build\arm\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%cd%\_build\arm64\Release\cppwinrt_fast_forwarder.lib

cppwinrt.sln

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_no_sourcelocatio
115115
{D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4}
116116
EndProjectSection
117117
EndProject
118+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D15C8430-A7CD-4616-BD84-243B26A9F1C2}"
119+
ProjectSection(SolutionItems) = preProject
120+
build_nuget.cmd = build_nuget.cmd
121+
build_prior_projection.cmd = build_prior_projection.cmd
122+
build_projection.cmd = build_projection.cmd
123+
build_test_all.cmd = build_test_all.cmd
124+
build_vsix.cmd = build_vsix.cmd
125+
compile_tests.cmd = compile_tests.cmd
126+
prepare_versionless_diffs.cmd = prepare_versionless_diffs.cmd
127+
README.md = README.md
128+
run_tests.cmd = run_tests.cmd
129+
EndProjectSection
130+
EndProject
118131
Global
119132
GlobalSection(SolutionConfigurationPlatforms) = preSolution
120133
Debug|ARM = Debug|ARM

nuget/Microsoft.Windows.CppWinRT.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
33
<metadata minClientVersion="2.5">
44
<id>Microsoft.Windows.CppWinRT</id>
5-
<version>1.0.0.0</version>
5+
<version>$target_version$</version>
66
<title>C++/WinRT Build Support</title>
77
<authors>Microsoft</authors>
88
<owners>Microsoft</owners>

strings/base_delegate.h

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,60 @@ namespace winrt::impl
66
#pragma warning(disable:4458) // declaration hides class member (okay because we do not use named members of base class)
77
#endif
88

9-
template <typename T, typename H>
10-
struct implements_delegate : abi_t<T>, H, update_module_lock
9+
struct implements_delegate_base
1110
{
12-
implements_delegate(H&& handler) : H(std::forward<H>(handler))
11+
WINRT_IMPL_NOINLINE uint32_t increment_reference() noexcept
1312
{
13+
return ++m_references;
1414
}
1515

16-
int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final
16+
WINRT_IMPL_NOINLINE uint32_t decrement_reference() noexcept
17+
{
18+
return --m_references;
19+
}
20+
21+
WINRT_IMPL_NOINLINE uint32_t query_interface(guid const& id, void** result, unknown_abi* derivedAbiPtr, guid const& derivedId) noexcept
1722
{
18-
if (is_guid_of<T>(id) || is_guid_of<Windows::Foundation::IUnknown>(id) || is_guid_of<IAgileObject>(id))
23+
if (id == derivedId || is_guid_of<Windows::Foundation::IUnknown>(id) || is_guid_of<IAgileObject>(id))
1924
{
20-
*result = static_cast<abi_t<T>*>(this);
21-
AddRef();
25+
*result = derivedAbiPtr;
26+
increment_reference();
2227
return 0;
2328
}
2429

2530
if (is_guid_of<IMarshal>(id))
2631
{
27-
return make_marshaler(this, result);
32+
return make_marshaler(derivedAbiPtr, result);
2833
}
2934

3035
*result = nullptr;
3136
return error_no_interface;
3237
}
3338

39+
private:
40+
atomic_ref_count m_references{ 1 };
41+
};
42+
43+
template <typename T, typename H>
44+
struct implements_delegate : abi_t<T>, implements_delegate_base, H, update_module_lock
45+
{
46+
implements_delegate(H&& handler) : H(std::forward<H>(handler))
47+
{
48+
}
49+
50+
int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final
51+
{
52+
return query_interface(id, result, static_cast<abi_t<T>*>(this), guid_of<T>());
53+
}
54+
3455
uint32_t __stdcall AddRef() noexcept final
3556
{
36-
return ++m_references;
57+
return increment_reference();
3758
}
3859

3960
uint32_t __stdcall Release() noexcept final
4061
{
41-
auto const remaining = --m_references;
62+
auto const remaining = decrement_reference();
4263

4364
if (remaining == 0)
4465
{
@@ -47,10 +68,6 @@ namespace winrt::impl
4768

4869
return remaining;
4970
}
50-
51-
private:
52-
53-
atomic_ref_count m_references{ 1 };
5471
};
5572

5673
template <typename T, typename H>
@@ -73,15 +90,16 @@ namespace winrt::impl
7390
return delegate;
7491
}
7592

93+
const auto id = guid_of<T>();
7694
com_ptr<IAgileReference> ref;
77-
get_agile_reference(guid_of<T>(), get_abi(delegate), ref.put_void());
95+
get_agile_reference(id, get_abi(delegate), ref.put_void());
7896

7997
if (ref)
8098
{
81-
return [ref = std::move(ref)](auto&& ... args)
99+
return [ref = std::move(ref), id](auto&& ... args)
82100
{
83101
T delegate;
84-
ref->Resolve(guid_of<T>(), put_abi(delegate));
102+
ref->Resolve(id, put_abi(delegate));
85103
return delegate(args...);
86104
};
87105
}
@@ -97,7 +115,7 @@ namespace winrt::impl
97115
};
98116

99117
template <typename H, typename R, typename... Args>
100-
struct variadic_delegate final : variadic_delegate_abi<R, Args...>, H, update_module_lock
118+
struct variadic_delegate final : variadic_delegate_abi<R, Args...>, implements_delegate_base, H, update_module_lock
101119
{
102120
variadic_delegate(H&& handler) : H(std::forward<H>(handler))
103121
{
@@ -117,25 +135,17 @@ namespace winrt::impl
117135

118136
int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final
119137
{
120-
if (is_guid_of<Windows::Foundation::IUnknown>(id) || is_guid_of<IAgileObject>(id))
121-
{
122-
*result = static_cast<unknown_abi*>(this);
123-
AddRef();
124-
return 0;
125-
}
126-
127-
*result = nullptr;
128-
return error_no_interface;
138+
return query_interface(id, result, static_cast<unknown_abi*>(this), guid_of<Windows::Foundation::IUnknown>());
129139
}
130140

131141
uint32_t __stdcall AddRef() noexcept final
132142
{
133-
return ++m_references;
143+
return increment_reference();
134144
}
135145

136146
uint32_t __stdcall Release() noexcept final
137147
{
138-
auto const remaining = --m_references;
148+
auto const remaining = decrement_reference();
139149

140150
if (remaining == 0)
141151
{
@@ -144,10 +154,6 @@ namespace winrt::impl
144154

145155
return remaining;
146156
}
147-
148-
private:
149-
150-
atomic_ref_count m_references{ 1 };
151157
};
152158

153159
template <typename R, typename... Args>

strings/base_events.h

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,24 @@ namespace winrt::impl
342342
return 1;
343343
}
344344

345+
WINRT_IMPL_NOINLINE inline bool report_failed_invoke()
346+
{
347+
int32_t const code = to_hresult();
348+
349+
static int32_t(__stdcall * handler)(int32_t, int32_t, void*) noexcept;
350+
impl::load_runtime_function(L"combase.dll", "RoTransformError", handler, fallback_RoTransformError);
351+
handler(code, 0, nullptr);
352+
353+
if (code == static_cast<int32_t>(0x80010108) || // RPC_E_DISCONNECTED
354+
code == static_cast<int32_t>(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)
355+
code == static_cast<int32_t>(0x89020001)) // JSCRIPT_E_CANTEXECUTE
356+
{
357+
return false;
358+
}
359+
360+
return true;
361+
}
362+
345363
template <typename Delegate, typename... Arg>
346364
bool invoke(Delegate const& delegate, Arg const&... args) noexcept
347365
{
@@ -351,18 +369,7 @@ namespace winrt::impl
351369
}
352370
catch (...)
353371
{
354-
int32_t const code = to_hresult();
355-
356-
static int32_t(__stdcall * handler)(int32_t, int32_t, void*) noexcept;
357-
impl::load_runtime_function(L"combase.dll", "RoTransformError", handler, fallback_RoTransformError);
358-
handler(code, 0, nullptr);
359-
360-
if (code == static_cast<int32_t>(0x80010108) || // RPC_E_DISCONNECTED
361-
code == static_cast<int32_t>(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)
362-
code == static_cast<int32_t>(0x89020001)) // JSCRIPT_E_CANTEXECUTE
363-
{
364-
return false;
365-
}
372+
return report_failed_invoke();
366373
}
367374

368375
return true;
@@ -387,28 +394,7 @@ WINRT_EXPORT namespace winrt
387394

388395
event_token add(delegate_type const& delegate)
389396
{
390-
event_token token{};
391-
392-
// Extends life of old targets array to release delegates outside of lock.
393-
delegate_array temp_targets;
394-
395-
{
396-
slim_lock_guard const change_guard(m_change);
397-
delegate_array new_targets = impl::make_event_array<delegate_type>((!m_targets) ? 1 : m_targets->size() + 1);
398-
399-
if (m_targets)
400-
{
401-
std::copy_n(m_targets->begin(), m_targets->size(), new_targets->begin());
402-
}
403-
404-
new_targets->back() = impl::make_agile_delegate(delegate);
405-
token = get_token(new_targets->back());
406-
407-
slim_lock_guard const swap_guard(m_swap);
408-
temp_targets = std::exchange(m_targets, std::move(new_targets));
409-
}
410-
411-
return token;
397+
return add_agile(impl::make_agile_delegate(delegate));
412398
}
413399

414400
void remove(event_token const token)
@@ -510,6 +496,32 @@ WINRT_EXPORT namespace winrt
510496

511497
private:
512498

499+
WINRT_IMPL_NOINLINE event_token add_agile(delegate_type delegate)
500+
{
501+
event_token token{};
502+
503+
// Extends life of old targets array to release delegates outside of lock.
504+
delegate_array temp_targets;
505+
506+
{
507+
slim_lock_guard const change_guard(m_change);
508+
delegate_array new_targets = impl::make_event_array<delegate_type>((!m_targets) ? 1 : m_targets->size() + 1);
509+
510+
if (m_targets)
511+
{
512+
std::copy_n(m_targets->begin(), m_targets->size(), new_targets->begin());
513+
}
514+
515+
new_targets->back() = std::move(delegate);
516+
token = get_token(new_targets->back());
517+
518+
slim_lock_guard const swap_guard(m_swap);
519+
temp_targets = std::exchange(m_targets, std::move(new_targets));
520+
}
521+
522+
return token;
523+
}
524+
513525
event_token get_token(delegate_type const& delegate) const noexcept
514526
{
515527
return event_token{ reinterpret_cast<int64_t>(WINRT_IMPL_EncodePointer(get_abi(delegate))) };

strings/base_implements.h

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,19 +1156,16 @@ namespace winrt::impl
11561156
return 0;
11571157
}
11581158

1159-
if constexpr (is_agile::value)
1160-
{
1161-
if (is_guid_of<IAgileObject>(id))
1162-
{
1163-
*object = get_unknown();
1164-
AddRef();
1165-
return 0;
1166-
}
1159+
return query_interface_common(id, object);
1160+
}
11671161

1168-
if (is_guid_of<IMarshal>(id))
1169-
{
1170-
return make_marshaler(get_unknown(), object);
1171-
}
1162+
WINRT_IMPL_NOINLINE int32_t query_interface_common(guid const& id, void** object) noexcept
1163+
{
1164+
if (is_guid_of<Windows::Foundation::IUnknown>(id))
1165+
{
1166+
*object = get_unknown();
1167+
AddRef();
1168+
return 0;
11721169
}
11731170

11741171
if constexpr (is_inspectable::value)
@@ -1181,13 +1178,6 @@ namespace winrt::impl
11811178
}
11821179
}
11831180

1184-
if (is_guid_of<Windows::Foundation::IUnknown>(id))
1185-
{
1186-
*object = get_unknown();
1187-
AddRef();
1188-
return 0;
1189-
}
1190-
11911181
if constexpr (is_weak_ref_source::value)
11921182
{
11931183
if (is_guid_of<impl::IWeakReferenceSource>(id))
@@ -1196,6 +1186,21 @@ namespace winrt::impl
11961186
return *object ? error_ok : error_bad_alloc;
11971187
}
11981188
}
1189+
1190+
if constexpr (is_agile::value)
1191+
{
1192+
if (is_guid_of<impl::IAgileObject>(id))
1193+
{
1194+
*object = get_unknown();
1195+
AddRef();
1196+
return 0;
1197+
}
1198+
1199+
if (is_guid_of<IMarshal>(id))
1200+
{
1201+
return make_marshaler(get_unknown(), object);
1202+
}
1203+
}
11991204

12001205
return query_interface_tearoff(id, object);
12011206
}

0 commit comments

Comments
 (0)