Skip to content

Commit 3708534

Browse files
committed
added xrDelegate
1 parent cbc2bbc commit 3708534

File tree

5 files changed

+508
-0
lines changed

5 files changed

+508
-0
lines changed

src/xrCore/xrCore.vcxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,9 @@ call .GitInfo.cmd</Command>
410410
<ClInclude Include="xrCore_benchmark_macros.h" />
411411
<ClInclude Include="xrDebug.h" />
412412
<ClInclude Include="xrDebug_macros.h" />
413+
<ClInclude Include="xrDelegate\xrDelegate.h" />
414+
<ClInclude Include="xrDelegate\xrDelegateArguments.h" />
415+
<ClInclude Include="xrDelegate\xrDelegateBinder.h" />
413416
<ClInclude Include="xrMemory.h" />
414417
<ClInclude Include="xrPool.h" />
415418
<ClInclude Include="xrsharedmem.h" />

src/xrCore/xrCore.vcxproj.filters

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@
112112
<Filter Include="Compression\lzo">
113113
<UniqueIdentifier>{c6342a66-65de-47b5-afe5-c51a7383edc0}</UniqueIdentifier>
114114
</Filter>
115+
<Filter Include="xrDelegate">
116+
<UniqueIdentifier>{b54073c2-213d-456f-b88d-8eeb0dd440b0}</UniqueIdentifier>
117+
</Filter>
115118
</ItemGroup>
116119
<ItemGroup>
117120
<ClCompile Include="FTimer.cpp">
@@ -683,6 +686,15 @@
683686
<ClInclude Include="FileCRC32.h">
684687
<Filter>FS</Filter>
685688
</ClInclude>
689+
<ClInclude Include="xrDelegate\xrDelegate.h">
690+
<Filter>xrDelegate</Filter>
691+
</ClInclude>
692+
<ClInclude Include="xrDelegate\xrDelegateArguments.h">
693+
<Filter>xrDelegate</Filter>
694+
</ClInclude>
695+
<ClInclude Include="xrDelegate\xrDelegateBinder.h">
696+
<Filter>xrDelegate</Filter>
697+
</ClInclude>
686698
</ItemGroup>
687699
<ItemGroup>
688700
<ResourceCompile Include="xrCore.rc">

src/xrCore/xrDelegate/xrDelegate.h

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
/***************************************************************************
2+
* Copyright (C) 2018 - Vast & Ray of Hope Development Team
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining
5+
* a copy of this software and associated documentation files (the
6+
* "Software"), to deal in the Software without restriction, including
7+
* without limitation the rights to use, copy, modify, merge, publish,
8+
* distribute, sublicense, and/or sell copies of the Software, and to
9+
* permit persons to whom the Software is furnished to do so, subject to
10+
* the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be
13+
* included in all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18+
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19+
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20+
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21+
* OTHER DEALINGS IN THE SOFTWARE.
22+
***************************************************************************/
23+
24+
#pragma once
25+
#include <functional>
26+
#include "xrDelegateArguments.h"
27+
28+
template<int>
29+
struct delegate_argument
30+
{};
31+
32+
namespace std
33+
{
34+
template<int N>
35+
struct is_placeholder<delegate_argument<N>>
36+
: integral_constant<int, N + 1> // the one is important
37+
{};
38+
}
39+
40+
template<typename Result>
41+
class xrAbstractDelegate
42+
{
43+
public:
44+
xrAbstractDelegate() = default;
45+
46+
xrAbstractDelegate(const xrAbstractDelegate& other)
47+
: d_handle(other.d_handle),
48+
d_functor_hash(other.d_functor_hash),
49+
d_function_hash(other.d_function_hash)
50+
{
51+
}
52+
53+
xrAbstractDelegate(xrAbstractDelegate&& other) noexcept
54+
: d_handle(other.d_handle),
55+
d_functor_hash(other.d_functor_hash),
56+
d_function_hash(other.d_function_hash)
57+
{
58+
}
59+
60+
xrAbstractDelegate& operator=(const xrAbstractDelegate& other)
61+
{
62+
if (this == &other)
63+
return *this;
64+
d_handle = other.d_handle;
65+
d_functor_hash = other.d_functor_hash;
66+
d_function_hash = other.d_function_hash;
67+
return *this;
68+
}
69+
70+
xrAbstractDelegate& operator=(xrAbstractDelegate&& other) noexcept
71+
{
72+
if (this == &other)
73+
return *this;
74+
d_handle = other.d_handle;
75+
d_functor_hash = other.d_functor_hash;
76+
d_function_hash = other.d_function_hash;
77+
return *this;
78+
}
79+
80+
virtual ~xrAbstractDelegate() = default;
81+
82+
virtual Result invoke_args(xrDelegateArguments& args) const = 0;
83+
84+
template<typename ... Args>
85+
Result invoke(Args ... args) const;
86+
87+
bool operator==(const xrAbstractDelegate<Result>& delegate) const
88+
{
89+
return d_handle == delegate.d_handle
90+
&& d_functor_hash == delegate.d_functor_hash
91+
&& d_function_hash == delegate.d_function_hash;
92+
}
93+
94+
protected:
95+
void* d_handle = nullptr;
96+
size_t d_functor_hash = 0;
97+
size_t d_function_hash = 0;
98+
};
99+
100+
template<typename Result, typename ... Args>
101+
class xrDelegate;
102+
103+
template<typename Result, typename ... Args>
104+
class xrDelegate<Result(Args...)> : public xrAbstractDelegate<Result>
105+
{
106+
public:
107+
using inherited = xrAbstractDelegate<Result>;
108+
using tuple_type = std::tuple<Args...>;
109+
using function_type = std::function<Result(Args...)>;
110+
111+
xrDelegate() = default;
112+
113+
xrDelegate(std::nullptr_t) {}
114+
115+
xrDelegate(const xrDelegate& other)
116+
: inherited(other),
117+
d_function(other.d_function)
118+
{
119+
}
120+
121+
xrDelegate(xrDelegate&& other) noexcept
122+
: inherited(std::move(other)),
123+
d_function(std::move(other.d_function))
124+
{
125+
}
126+
127+
xrDelegate& operator=(const xrDelegate& other)
128+
{
129+
if (this == &other)
130+
return *this;
131+
inherited::operator =(other);
132+
d_function = other.d_function;
133+
return *this;
134+
}
135+
136+
xrDelegate& operator=(xrDelegate&& other) noexcept
137+
{
138+
if (this == &other)
139+
return *this;
140+
inherited::operator =(std::move(other));
141+
d_function = std::move(other.d_function);
142+
return *this;
143+
}
144+
145+
template<typename Fx>
146+
xrDelegate(Fx fx)
147+
{
148+
bind(fx);
149+
}
150+
151+
template<typename Fx, typename Tx>
152+
xrDelegate(Fx fx, Tx tx)
153+
{
154+
bind(fx, tx);
155+
}
156+
157+
~xrDelegate() = default;
158+
159+
template<typename TClass, typename TFunction>
160+
void bind(TClass fx, TFunction tx)
161+
{
162+
using sequence = std::make_index_sequence<sizeof ... (Args)>;
163+
auto functor = bind_impl(sequence{}, tx, fx);
164+
inherited::d_function_hash = typeid(TFunction).hash_code();
165+
inherited::d_functor_hash = typeid(decltype(functor)).hash_code();
166+
inherited::d_handle = fx;
167+
d_function = functor;
168+
}
169+
170+
template<typename TFunction>
171+
void bind(TFunction fx)
172+
{
173+
using sequence = std::make_index_sequence<sizeof ... (Args)>;
174+
auto functor = bind_impl(sequence{}, fx);
175+
inherited::d_function_hash = typeid(TFunction).hash_code();
176+
inherited::d_functor_hash = typeid(decltype(functor)).hash_code();
177+
d_function = functor;
178+
}
179+
180+
void reset()
181+
{
182+
d_function = nullptr;
183+
inherited::d_handle = nullptr;
184+
inherited::d_functor_hash = 0;
185+
inherited::d_function_hash = 0;
186+
}
187+
188+
Result invoke_args(xrDelegateArguments& args) const override
189+
{
190+
if constexpr (sizeof ... (Args) > 0)
191+
{
192+
tuple_type& values = args.get<Args...>().values();
193+
using index_sequence = std::make_index_sequence<std::tuple_size<typename std::decay<tuple_type>::type>::value>;
194+
195+
if constexpr (std::is_same_v<Result, void>)
196+
run(values, index_sequence{});
197+
else
198+
return run(values, index_sequence{});
199+
}
200+
else if constexpr (std::is_same_v<Result, void>)
201+
d_function();
202+
else
203+
return d_function();
204+
}
205+
206+
Result invoke(Args ... args) const
207+
{
208+
if constexpr (std::is_same_v<Result, void>)
209+
d_function(std::forward<Args>(args)...);
210+
else
211+
return d_function(std::forward<Args>(args)...);
212+
}
213+
214+
const function_type& get_function() const
215+
{
216+
return d_function;
217+
}
218+
219+
bool empty() const
220+
{
221+
return d_function == nullptr;
222+
}
223+
224+
xrDelegate& operator=(std::nullptr_t) noexcept
225+
{
226+
reset();
227+
return *this;
228+
}
229+
230+
Result operator()(Args ... args) const
231+
{
232+
if constexpr (std::is_same_v<Result, void>)
233+
invoke(std::forward<Args>(args)...);
234+
else
235+
return invoke(std::forward<Args>(args)...);
236+
}
237+
238+
bool operator==(const xrDelegate<Result(Args...)>& delegate) const
239+
{
240+
return inherited::d_handle == delegate.d_handle
241+
&& inherited::d_functor_hash == delegate.d_functor_hash
242+
&& inherited::d_function_hash == delegate.d_function_hash;
243+
}
244+
245+
operator bool() const
246+
{
247+
return !empty();
248+
}
249+
250+
bool operator!() const
251+
{
252+
return empty();
253+
}
254+
255+
private:
256+
template<std::size_t... index>
257+
Result run(tuple_type& tup, std::index_sequence<index...>) const
258+
{
259+
return d_function(std::forward<Args>(std::get<index>(tup))...);
260+
}
261+
262+
template<typename ... Fx, size_t... Is>
263+
static auto bind_impl(std::integer_sequence<size_t, Is...>, Fx&& ... fx)
264+
{
265+
return std::bind(fx ..., delegate_argument<Is>{}...);
266+
}
267+
268+
function_type d_function = nullptr;
269+
};
270+
271+
template <typename Result>
272+
template <typename ... Args>
273+
Result xrAbstractDelegate<Result>::invoke(Args... args) const
274+
{
275+
auto self = const_cast<xrAbstractDelegate<Result>*>(this);
276+
return static_cast<xrDelegate<Result(Args...)>*>(self)->invoke(args...);
277+
}
278+
279+
#include "xrDelegateBinder.h"
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/***************************************************************************
2+
* Copyright (C) 2018 - Vast & Ray of Hope Development Team
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining
5+
* a copy of this software and associated documentation files (the
6+
* "Software"), to deal in the Software without restriction, including
7+
* without limitation the rights to use, copy, modify, merge, publish,
8+
* distribute, sublicense, and/or sell copies of the Software, and to
9+
* permit persons to whom the Software is furnished to do so, subject to
10+
* the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be
13+
* included in all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18+
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19+
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20+
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21+
* OTHER DEALINGS IN THE SOFTWARE.
22+
***************************************************************************/
23+
24+
#pragma once
25+
26+
template<typename ... Args>
27+
class xrDelegateArgumentsTypes;
28+
29+
class xrDelegateArguments
30+
{
31+
public:
32+
virtual ~xrDelegateArguments() = default;
33+
34+
template<typename ... Args>
35+
xrDelegateArgumentsTypes<Args...>& get()
36+
{
37+
xrDelegateArguments* self = const_cast<xrDelegateArguments*>(this);
38+
return static_cast<xrDelegateArgumentsTypes<Args...>&>(*self);
39+
}
40+
};
41+
42+
template<typename ... Args>
43+
class xrDelegateArgumentsTypes : public xrDelegateArguments
44+
{
45+
public:
46+
using tuple_type = std::tuple<Args...>;
47+
48+
xrDelegateArgumentsTypes(Args&& ... args) : d_args(args...) {}
49+
50+
tuple_type& values() { return d_args; }
51+
52+
auto&& first() { return std::get<0>(d_args); }
53+
54+
private:
55+
tuple_type d_args;
56+
};

0 commit comments

Comments
 (0)