OpenVPN 3 Core Library
Loading...
Searching...
No Matches
test_typeindex.cpp
Go to the documentation of this file.
1// This test demonstrates an alternative to dynamic_cast
2// using std::typeindex that is much faster.
3
4#include "test_common.hpp"
5
6#include <typeindex>
7#include <vector>
8#include <utility>
9
11#include <openvpn/common/rc.hpp>
13
14using namespace openvpn;
15
16namespace {
17struct Base : public RC<thread_unsafe_refcount>
18{
19 public:
20 typedef RCPtr<Base> Ptr;
21
22 virtual std::string to_string() const = 0;
23
24 std::type_index type() const
25 {
26 return type_;
27 }
28
29 protected:
30 Base(std::type_index &&type)
31 : type_(std::move(type))
32 {
33 }
34
35 private:
36 const std::type_index type_;
37};
38
39template <typename T>
40class Wrapper : public Base
41{
42 public:
43 Wrapper(T &&obj_arg)
44 : Base(static_type()),
45 obj(std::move(obj_arg))
46 {
47 }
48
49 // this is like dynamic cast on steroids! (~1 ns)
50 static const Wrapper *self(const Base *maybe_my_type)
51 {
52 if (maybe_my_type->type() == static_type())
53 return static_cast<const Wrapper *>(maybe_my_type);
54 else
55 return nullptr;
56 }
57
58 virtual std::string to_string() const override
59 {
60 return "value=" + StringTempl::to_string(obj) + " obj_size=" + std::to_string(sizeof(obj));
61 }
62
63 static std::type_index static_type()
64 {
65 return std::type_index(typeid(Wrapper));
66 }
67
68 T obj;
69};
70
71struct Vec : public std::vector<Base::Ptr>
72{
73 std::string to_string() const
74 {
75 std::string ret;
76 for (const auto &e : *this)
77 {
78 ret += e->to_string();
79 ret += '\n';
80 }
81 return ret;
82 }
83};
84
85template <typename T>
86static Base::Ptr create(T &&obj)
87{
88 return Base::Ptr(new Wrapper<T>(std::move(obj)));
89}
90
91static Vec create_vec()
92{
93 Vec vec;
94 vec.emplace_back(create(1));
95 vec.emplace_back(create(2));
96 vec.emplace_back(create(3.14159));
97 vec.emplace_back(create(std::string("Hello")));
98 vec.emplace_back(create(std::string("World!")));
99 vec.emplace_back(create(true));
100 vec.emplace_back(create(false));
101 return vec;
102}
103} // namespace
104
105// simple test of self()
106TEST(typeindex, test)
107{
108 typedef Wrapper<std::string> StringWrap;
109
110 const Vec vec = create_vec();
111
112 OPENVPN_LOG("CONTENTS...");
113 OPENVPN_LOG_STRING(vec.to_string());
114
115 OPENVPN_LOG("STRINGS...");
116 for (const auto &e : vec)
117 {
118 const StringWrap *s = StringWrap::self(e.get());
119 if (s)
120 OPENVPN_LOG(s->obj);
121 }
122}
123
124#ifndef INSTRUMENTATION_SLOWDOWN
125
126// test performance of self() as alternative to dynamic_cast
127TEST(typeindex, perf_test_fast)
128{
129 typedef Wrapper<std::string> StringWrap;
130
131 const size_t N = 100000000;
132
133 const Vec vec = create_vec();
134 const size_t size = vec.size();
135 size_t n_strings = 0;
136 size_t i = 0;
137 for (size_t count = 0; count < N; ++count)
138 {
139 const StringWrap *s = StringWrap::self(vec[i].get());
140 if (s)
141 ++n_strings;
142 if (++i >= size)
143 i = 0;
144 }
145 OPENVPN_LOG("PERF " << n_strings << '/' << N);
146 ASSERT_EQ(n_strings, 28571428u);
147}
148
149// as a control, test performance of dynamic_cast
150TEST(typeindex, perf_test_dynamic)
151{
152 typedef Wrapper<std::string> StringWrap;
153
154 const size_t N = 100000000;
155
156 const Vec vec = create_vec();
157 const size_t size = vec.size();
158 size_t n_strings = 0;
159 size_t i = 0;
160 for (size_t count = 0; count < N; ++count)
161 {
162 const StringWrap *s = dynamic_cast<const StringWrap *>(vec[i].get());
163 if (s)
164 ++n_strings;
165 if (++i >= size)
166 i = 0;
167 }
168 OPENVPN_LOG("PERF " << n_strings << '/' << N);
169 ASSERT_EQ(n_strings, 28571428u);
170}
171
172#endif
The smart pointer class.
Definition rc.hpp:119
Reference count base class for objects tracked by RCPtr. Disallows copying and assignment.
Definition rc.hpp:912
RCPtr< RC > Ptr
Definition rc.hpp:914
#define OPENVPN_LOG(args)
#define OPENVPN_LOG_STRING(str)
std::string to_string(std::nullptr_t)
HTTPBase< HTTPCore, Config, Status, HTTP::ReplyType, ContentInfo, olong, RC< thread_unsafe_refcount > > Base
Definition httpcli.hpp:347
void to_string(const Json::Value &root, std::string &dest, const NAME &name, const TITLE &title)
std::string ret
void test()
Definition test_rc.cpp:80
TEST(typeindex, test)