Skip to content

Commit 71f7592

Browse files
committed
Optimize activation factory using binary search
1 parent 856eaff commit 71f7592

1 file changed

Lines changed: 82 additions & 47 deletions

File tree

‎cppwinrt/component_writers.h‎

Lines changed: 82 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,7 @@ namespace cppwinrt
7676
return;
7777
}
7878

79-
if (settings.component_opt)
80-
{
81-
auto format = R"(void* winrt_make_%();
82-
)";
83-
84-
w.write(format, get_impl_name(type.TypeNamespace(), type.TypeName()));
85-
}
86-
else
79+
if (!settings.component_opt)
8780
{
8881
auto format = R"(#include "%.h"
8982
)";
@@ -105,42 +98,86 @@ namespace cppwinrt
10598

10699
if (settings.component_opt)
107100
{
108-
auto format = R"(
109-
if (requal(name, L"%.%"))
110-
{
111-
return winrt_make_%();
112-
}
101+
auto format = R"(void* winrt_make_%();
113102
)";
114103

115-
w.write(format,
116-
type_namespace,
117-
type_name,
118-
impl_name);
104+
w.write(format, impl_name);
119105
}
120106
else
121107
{
122-
auto format = R"(
123-
if (requal(name, L"%.%"))
124-
{
125-
return winrt::detach_abi(winrt::make<winrt::@::factory_implementation::%>());
126-
}
108+
auto format = R"(void* winrt_make_%()
109+
{
110+
return winrt::detach_abi(winrt::make<winrt::@::factory_implementation::%>());
111+
}
127112
)";
128113

129114
w.write(format,
130-
type_namespace,
131-
type_name,
115+
impl_name,
132116
type_namespace,
133117
type_name);
134118
}
135119
}
136120

121+
static void add_component_manifest_entry(TypeDef const& type, std::vector<std::string>& manifest)
122+
{
123+
if (!has_factory_members(type) || is_always_disabled(type))
124+
{
125+
return;
126+
}
127+
128+
std::string name;
129+
name += type.TypeNamespace();
130+
name += '.';
131+
name += type.TypeName();
132+
manifest.push_back(std::move(name));
133+
}
134+
137135
static void write_module_g_cpp(writer& w, std::vector<TypeDef> const& classes)
138136
{
139137
if (!settings.modules)
140138
{
141139
w.write_root_include("base");
142140
}
143-
auto format = R"(%
141+
142+
for (auto&& type : classes)
143+
{
144+
write_component_include(w, type);
145+
}
146+
147+
std::vector<std::string> manifest;
148+
149+
for (auto&& type : classes)
150+
{
151+
add_component_manifest_entry(type, manifest);
152+
}
153+
154+
// Sort the strings so that binary search can be used.
155+
std::sort(manifest.begin(), manifest.end());
156+
157+
w.write("#define WINRT_ACTIVATION_TABLE(X)\\\n");
158+
159+
for (std::size_t i = 0; i + 1 < manifest.size(); ++i)
160+
{
161+
w.write(std::string{ " X(winrt_make_" } + get_impl_name(manifest[i]) + ", L\"" + manifest[i] + "\") \\\n");
162+
}
163+
164+
if (!manifest.empty())
165+
{
166+
w.write(std::string{ " X(winrt_make_" } + get_impl_name(manifest.back()) + ", L\"" + manifest.back() + "\")\n");
167+
}
168+
169+
auto declarations = R"(
170+
#define WINRT_DECLARE_FUNC(func, name) void* func();
171+
WINRT_ACTIVATION_TABLE(WINRT_DECLARE_FUNC)
172+
)";
173+
w.write(declarations);
174+
175+
for (auto&& type : classes)
176+
{
177+
write_component_activation(w, type);
178+
}
179+
180+
auto format = R"(
144181
bool __stdcall %_can_unload_now() noexcept
145182
{
146183
if (winrt::get_module_lock())
@@ -154,20 +191,31 @@ bool __stdcall %_can_unload_now() noexcept
154191
155192
void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view const& name)
156193
{
157-
auto requal = [](std::wstring_view const& left, std::wstring_view const& right) noexcept
194+
#if %
195+
static constexpr std::wstring_view names[] =
158196
{
159-
return std::equal(left.rbegin(), left.rend(), right.rbegin(), right.rend());
197+
#define WINRT_NAME_LIST(func, name) name,
198+
WINRT_ACTIVATION_TABLE(WINRT_NAME_LIST)
160199
};
161-
%
200+
201+
using make_t = void* (*)();
202+
static constexpr make_t makes[] =
203+
{
204+
#define WINRT_MAKE_LIST(func, name) func,
205+
WINRT_ACTIVATION_TABLE(WINRT_MAKE_LIST)
206+
};
207+
208+
auto it = std::lower_bound(std::begin(names), std::end(names), name);
209+
if (it != std::end(names) && *it == name)
210+
{
211+
return makes[it - std::begin(names)]();
212+
}
213+
#endif
162214
return nullptr;
163215
}
164216
)";
165217

166-
w.write(format,
167-
bind_each<write_component_include>(classes),
168-
settings.component_lib,
169-
settings.component_lib,
170-
bind_each<write_component_activation>(classes));
218+
w.write(format, settings.component_lib, settings.component_lib, manifest.empty() ? 0 : 1);
171219

172220
if (settings.component_lib != "winrt")
173221
{
@@ -379,21 +427,8 @@ catch (...) { return winrt::to_hresult(); }
379427
{
380428
auto type_name = type.TypeName();
381429
auto type_namespace = type.TypeNamespace();
382-
auto impl_name = get_impl_name(type_namespace, type_name);
383430

384-
if (has_factory_members(w, type))
385-
{
386-
auto format = R"(void* winrt_make_%()
387-
{
388-
return winrt::detach_abi(winrt::make<winrt::@::factory_implementation::%>());
389-
}
390-
)";
391-
392-
w.write(format,
393-
impl_name,
394-
type_namespace,
395-
type_name);
396-
}
431+
write_component_activation(w, type);
397432

398433
if (!settings.component_opt)
399434
{

0 commit comments

Comments
 (0)