Skip to content

Commit 7fd449e

Browse files
committed
more policy splitting
1 parent 25b48ad commit 7fd449e

12 files changed

+471
-409
lines changed

include/yorel/yomm2/policies/basic_error_output.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11

2+
// Copyright (c) 2018-2024 Jean-Louis Leroy
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// See accompanying file LICENSE_1_0.txt
5+
// or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
27
#ifndef YOREL_YOMM2_POLICY_BASIC_ERROR_OUTPUT_HPP
38
#define YOREL_YOMM2_POLICY_BASIC_ERROR_OUTPUT_HPP
49

@@ -8,9 +13,16 @@ namespace yorel {
813
namespace yomm2 {
914
namespace policy {
1015

16+
template<class Policy, typename Stream = detail::ostderr>
17+
struct yOMM2_API_gcc basic_error_output : virtual error_output {
18+
static Stream error_stream;
19+
};
20+
21+
template<class Policy, typename Stream>
22+
Stream basic_error_output<Policy, Stream>::error_stream;
23+
1124
}
1225
}
1326
}
1427

1528
#endif
16-

include/yorel/yomm2/policies/basic_indirect_vptr.hpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11

2+
// Copyright (c) 2018-2024 Jean-Louis Leroy
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// See accompanying file LICENSE_1_0.txt
5+
// or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
27
#ifndef YOREL_YOMM2_POLICY_BASIC_INDIRECT_VPTR_HPP
38
#define YOREL_YOMM2_POLICY_BASIC_INDIRECT_VPTR_HPP
49

@@ -8,9 +13,17 @@ namespace yorel {
813
namespace yomm2 {
914
namespace policy {
1015

16+
template<class Policy>
17+
struct yOMM2_API_gcc basic_indirect_vptr : virtual indirect_vptr {
18+
static std::vector<std::uintptr_t const* const*> indirect_vptrs;
19+
};
20+
21+
template<class Policy>
22+
std::vector<std::uintptr_t const* const*>
23+
basic_indirect_vptr<Policy>::indirect_vptrs;
24+
1125
}
1226
}
1327
}
1428

1529
#endif
16-

include/yorel/yomm2/policies/basic_trace_output.hpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11

2+
// Copyright (c) 2018-2024 Jean-Louis Leroy
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// See accompanying file LICENSE_1_0.txt
5+
// or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
27
#ifndef YOREL_YOMM2_POLICY_BASIC_TRACE_OUTPUT_HPP
38
#define YOREL_YOMM2_POLICY_BASIC_TRACE_OUTPUT_HPP
49

@@ -8,9 +13,23 @@ namespace yorel {
813
namespace yomm2 {
914
namespace policy {
1015

16+
template<class Policy, typename Stream = detail::ostderr>
17+
struct yOMM2_API_gcc basic_trace_output : virtual trace_output {
18+
static Stream trace_stream;
19+
static bool trace_enabled;
20+
};
21+
22+
template<class Policy, typename Stream>
23+
Stream basic_trace_output<Policy, Stream>::trace_stream;
24+
25+
template<class Policy, typename Stream>
26+
bool basic_trace_output<Policy, Stream>::trace_enabled([]() {
27+
auto env = getenv("YOMM2_TRACE");
28+
return env && *env++ == '1' && *env++ == 0;
29+
}());
30+
1131
}
1232
}
1333
}
1434

1535
#endif
16-

include/yorel/yomm2/policies/core.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// Copyright (c) 2018-2024 Jean-Louis Leroy
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// See accompanying file LICENSE_1_0.txt
4+
// or copy at http://www.boost.org/LICENSE_1_0.txt)
5+
16
#ifndef YOREL_YOMM2_POLICIES_CORE_HPP
27
#define YOREL_YOMM2_POLICIES_CORE_HPP
38

include/yorel/yomm2/policies/fast_perfect_hash.hpp

Lines changed: 185 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11

2+
// Copyright (c) 2018-2024 Jean-Louis Leroy
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// See accompanying file LICENSE_1_0.txt
5+
// or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
27
#ifndef YOREL_YOMM2_POLICY_FAST_PERFECT_HASH_HPP
38
#define YOREL_YOMM2_POLICY_FAST_PERFECT_HASH_HPP
49

@@ -8,9 +13,188 @@ namespace yorel {
813
namespace yomm2 {
914
namespace policy {
1015

16+
template<class Policy>
17+
struct yOMM2_API_gcc fast_perfect_hash : virtual type_hash {
18+
struct report {
19+
std::size_t method_table_size, dispatch_table_size;
20+
std::size_t hash_search_attempts;
21+
};
22+
23+
static type_id hash_mult;
24+
static std::size_t hash_shift;
25+
static std::size_t hash_length;
26+
static std::size_t hash_min;
27+
static std::size_t hash_max;
28+
29+
#ifdef _MSC_VER
30+
__forceinline
31+
#endif
32+
static type_id
33+
hash_type_id(type_id type) {
34+
return (hash_mult * type) >> hash_shift;
35+
}
36+
37+
template<typename ForwardIterator>
38+
static void hash_initialize(ForwardIterator first, ForwardIterator last) {
39+
std::vector<type_id> buckets;
40+
hash_initialize(first, last, buckets);
41+
}
42+
43+
template<typename ForwardIterator>
44+
static void hash_initialize(
45+
ForwardIterator first, ForwardIterator last,
46+
std::vector<type_id>& buckets);
47+
};
48+
49+
template<class Policy>
50+
template<typename ForwardIterator>
51+
void fast_perfect_hash<Policy>::hash_initialize(
52+
ForwardIterator first, ForwardIterator last,
53+
std::vector<type_id>& buckets) {
54+
using namespace policy;
55+
56+
constexpr bool trace_enabled = Policy::template has_facet<trace_output>;
57+
const auto N = std::distance(first, last);
58+
59+
if constexpr (trace_enabled) {
60+
if (Policy::trace_enabled) {
61+
Policy::trace_stream << "Finding hash factor for " << N
62+
<< " types\n";
63+
}
64+
}
65+
66+
std::default_random_engine rnd(13081963);
67+
std::size_t total_attempts = 0;
68+
std::size_t M = 1;
69+
70+
for (auto size = N * 5 / 4; size >>= 1;) {
71+
++M;
72+
}
73+
74+
std::uniform_int_distribution<type_id> uniform_dist;
75+
76+
for (std::size_t pass = 0; pass < 4; ++pass, ++M) {
77+
hash_shift = 8 * sizeof(type_id) - M;
78+
auto hash_size = 1 << M;
79+
80+
if constexpr (trace_enabled) {
81+
if (Policy::trace_enabled) {
82+
Policy::trace_stream << " trying with M = " << M << ", "
83+
<< hash_size << " buckets\n";
84+
}
85+
}
86+
87+
bool found = false;
88+
std::size_t attempts = 0;
89+
buckets.resize(hash_size);
90+
hash_length = 0;
91+
92+
while (!found && attempts < 100000) {
93+
std::fill(buckets.begin(), buckets.end(), static_cast<type_id>(-1));
94+
++attempts;
95+
++total_attempts;
96+
found = true;
97+
hash_mult = uniform_dist(rnd) | 1;
98+
99+
for (auto iter = first; iter != last; ++iter) {
100+
for (auto type_iter = iter->type_id_begin();
101+
type_iter != iter->type_id_end(); ++type_iter) {
102+
auto type = *type_iter;
103+
auto index = (type * hash_mult) >> hash_shift;
104+
hash_min = (std::min)(hash_min, index);
105+
hash_max = (std::max)(hash_max, index);
106+
107+
if (buckets[index] != static_cast<type_id>(-1)) {
108+
found = false;
109+
break;
110+
}
111+
112+
buckets[index] = type;
113+
}
114+
}
115+
}
116+
117+
// metrics.hash_search_attempts = total_attempts;
118+
// metrics.hash_search_time =
119+
// std::chrono::steady_clock::now() - start_time;
120+
// metrics.hash_table_size = hash_size;
121+
122+
if (found) {
123+
hash_length = hash_max + 1;
124+
125+
if constexpr (trace_enabled) {
126+
if (Policy::trace_enabled) {
127+
Policy::trace_stream << " found " << hash_mult << " after "
128+
<< total_attempts
129+
<< " attempts; min = " << hash_min
130+
<< ", max = " << hash_max << "\n";
131+
}
132+
}
133+
134+
return;
135+
}
136+
}
137+
138+
hash_search_error error;
139+
error.attempts = total_attempts;
140+
// error.duration = std::chrono::steady_clock::now() - start_time;
141+
error.buckets = 1 << M;
142+
143+
if constexpr (has_facet<Policy, error_handler>) {
144+
Policy::error(error_type(error));
145+
}
146+
147+
abort();
148+
}
149+
150+
template<class Policy>
151+
type_id fast_perfect_hash<Policy>::hash_mult;
152+
template<class Policy>
153+
std::size_t fast_perfect_hash<Policy>::hash_shift;
154+
template<class Policy>
155+
std::size_t fast_perfect_hash<Policy>::hash_length;
156+
template<class Policy>
157+
std::size_t fast_perfect_hash<Policy>::hash_min;
158+
template<class Policy>
159+
std::size_t fast_perfect_hash<Policy>::hash_max;
160+
161+
template<class Policy>
162+
struct yOMM2_API_gcc checked_perfect_hash : virtual fast_perfect_hash<Policy>,
163+
virtual runtime_checks {
164+
static std::vector<type_id> control;
165+
166+
static type_id hash_type_id(type_id type) {
167+
auto index = fast_perfect_hash<Policy>::hash_type_id(type);
168+
169+
if (index >= fast_perfect_hash<Policy>::hash_length ||
170+
control[index] != type) {
171+
using namespace policy;
172+
173+
if constexpr (Policy::template has_facet<error_handler>) {
174+
unknown_class_error error;
175+
error.context = unknown_class_error::update;
176+
error.type = type;
177+
Policy::error(error);
178+
}
179+
180+
abort();
181+
}
182+
183+
return index;
184+
}
185+
186+
template<typename ForwardIterator>
187+
static void hash_initialize(ForwardIterator first, ForwardIterator last) {
188+
fast_perfect_hash<Policy>::hash_initialize(first, last, control);
189+
control.resize(fast_perfect_hash<Policy>::hash_length);
190+
}
191+
};
192+
193+
template<class Policy>
194+
std::vector<type_id> checked_perfect_hash<Policy>::control;
195+
11196
}
12197
}
13198
}
14199

15200
#endif
16-

include/yorel/yomm2/policies/minimal_rtti.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11

2+
// Copyright (c) 2018-2024 Jean-Louis Leroy
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// See accompanying file LICENSE_1_0.txt
5+
// or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
27
#ifndef YOREL_YOMM2_POLICY_MINIMAL_RTTI_HPP
38
#define YOREL_YOMM2_POLICY_MINIMAL_RTTI_HPP
49

@@ -8,9 +13,16 @@ namespace yorel {
813
namespace yomm2 {
914
namespace policy {
1015

16+
struct minimal_rtti : virtual rtti {
17+
template<typename T>
18+
static type_id static_type() {
19+
static char id;
20+
return reinterpret_cast<type_id>(&id);
21+
}
22+
};
23+
1124
}
1225
}
1326
}
1427

1528
#endif
16-

include/yorel/yomm2/policies/std_rtti.hpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11

2+
// Copyright (c) 2018-2024 Jean-Louis Leroy
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// See accompanying file LICENSE_1_0.txt
5+
// or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
27
#ifndef YOREL_YOMM2_POLICY_STD_RTTI_HPP
38
#define YOREL_YOMM2_POLICY_STD_RTTI_HPP
49

@@ -8,9 +13,39 @@ namespace yorel {
813
namespace yomm2 {
914
namespace policy {
1015

16+
struct std_rtti : virtual rtti {
17+
#ifndef BOOST_NO_RTTI
18+
template<class Class>
19+
static type_id static_type() {
20+
auto tip = &typeid(Class);
21+
return reinterpret_cast<type_id>(tip);
22+
}
23+
24+
template<class Class>
25+
static type_id dynamic_type(const Class& obj) {
26+
auto tip = &typeid(obj);
27+
return reinterpret_cast<type_id>(tip);
28+
}
29+
30+
template<typename Stream>
31+
static void type_name(type_id type, Stream& stream) {
32+
stream << boost::core::demangle(
33+
reinterpret_cast<const std::type_info*>(type)->name());
34+
}
35+
36+
static std::type_index type_index(type_id type) {
37+
return std::type_index(*reinterpret_cast<const std::type_info*>(type));
38+
}
39+
40+
template<typename D, typename B>
41+
static D dynamic_cast_ref(B&& obj) {
42+
return dynamic_cast<D>(obj);
43+
}
44+
#endif
45+
};
46+
1147
}
1248
}
1349
}
1450

1551
#endif
16-

0 commit comments

Comments
 (0)