/
CallExtractor.h
120 lines (102 loc) · 4.05 KB
/
CallExtractor.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#pragma once
#include "DataFlow.h"
#include "Decompose.h"
#include "AutoPacket.h"
#include "auto_arg.h"
class Deferred;
// The type of the call centralizer
typedef void(*t_extractedCall)(const AnySharedPointer& obj, AutoPacket&, const autowiring::DataFill&);
/// <summary>
/// Specialization for immediate mode cases
/// </summary>
template<class MemFn>
struct CallExtractor;
template<class RetType, class... Args>
struct CallExtractor<RetType (*)(Args...)>:
Decompose<RetType(*)(Args...)>
{
static const bool deferred = false;
/// <summary>
/// Binder struct, lets us refer to an instance of Call by type
/// </summary>
static void Call(const AnySharedPointer& obj, AutoPacket& autoPacket, const autowiring::DataFill& satisfaction) {
const void* pfn = obj->ptr();
// This is the true type of the input, it's the fnptr itself, not a function object
typedef RetType(*t_pfn)(Args...);
// Handoff
((t_pfn)pfn)(
auto_arg<Args>(autoPacket.shared_from_this(), *satisfaction.source(typeid(typename auto_arg<Args>::base_type)))...
);
}
};
template<class T, class... Args>
struct CallExtractor<void (T::*)(Args...)>:
Decompose<void (T::*)(Args...)>
{
static const bool stateless = false;
static const bool deferred = false;
static const size_t N = sizeof...(Args);
/// <summary>
/// Binder struct, lets us refer to an instance of Call by type
/// </summary>
template<void(T::*memFn)(Args...)>
static void Call(const AnySharedPointer& obj, AutoPacket& autoPacket, const autowiring::DataFill& satisfaction) {
const void* pObj = obj->ptr();
// This exception type indicates that an attempt was made to construct an AutoFilterDescriptor with an
// AnySharedPointer which was not the type of its own member function. Be sure to cast the AnySharedPointer
// to the correct foundation type before attempting to construct an AutoFilterDescriptor.
assert(typeid(typename SelectTypeUnifier<T>::type) == obj->type());
// Handoff
(((T*) pObj)->*memFn)(
auto_arg<Args>(autoPacket.shared_from_this(), *satisfaction.source(typeid(typename auto_arg<Args>::base_type)))...
);
}
};
/// <summary>
/// Specialization for stateless AutoFilter routines
/// </summary>
template<class T, class... Args>
struct CallExtractor<void (T::*)(Args...) const> :
Decompose<void (T::*)(Args...)>
{
static const bool stateless = true;
static const bool deferred = false;
static const size_t N = sizeof...(Args);
template<void(T::*memFn)(Args...) const>
static void Call(const AnySharedPointer& obj, AutoPacket& autoPacket, const autowiring::DataFill& satisfaction) {
const void* pObj = obj->ptr();
// Handoff
(((const T*) pObj)->*memFn)(
auto_arg<Args>(autoPacket.shared_from_this(), *satisfaction.source(typeid(typename auto_arg<Args>::base_type)))...
);
}
};
/// <summary>
/// Specialization for deferred cases
/// </summary>
template<class T, class... Args>
struct CallExtractor<Deferred (T::*)(Args...)>:
Decompose<void (T::*)(Args...)>
{
static const bool stateless = false;
static const bool deferred = true;
static const size_t N = sizeof...(Args);
template<Deferred(T::*memFn)(Args...)>
static void Call(const AnySharedPointer& obj, AutoPacket& autoPacket, const autowiring::DataFill& satisfaction) {
const void* pObj = obj->ptr();
// Obtain a shared pointer of the AutoPacket in order to ensure the packet
// stays resident when we pend this lambda to the destination object's
// dispatch queue.
auto pAutoPacket = autoPacket.shared_from_this();
// Pend the call to this object's dispatch queue:
// WARNING: The autowiring::DataFill information will be referenced,
// since it should be from a SatCounter associated to autoPacket,
// and will therefore have the same lifecycle as the AutoPacket.
*(T*) pObj += [pObj, pAutoPacket, &satisfaction] {
(((T*) pObj)->*memFn)(
auto_arg<Args>(pAutoPacket, *satisfaction.source(typeid(typename auto_arg<Args>::base_type)))...
);
};
}
};