DelegateMQ
Loading...
Searching...
No Matches
make_tuple_heap.h
Go to the documentation of this file.
1#ifndef _MAKE_TUPLE_HEAP_H
2#define _MAKE_TUPLE_HEAP_H
3
4// @see https://github.com/endurodave/DelegateMQ
5// David Lafreniere, Aug 2020.
6
19
20#include <tuple>
21#include <list>
22#include <memory>
23#include <type_traits>
24#include "DelegateOpt.h"
25
26namespace dmq
27{
28// std::shared_ptr reference arguments are not allowed with asynchronous delegates as the behavior is
29// undefined. In other words:
30// void MyFunc(std::shared_ptr<T> data) // Ok!
31// void MyFunc(std::shared_ptr<T>* data) // Error if DelegateAsync or DelegateSpAsync target!
32template<class T>
33struct is_shared_ptr : std::false_type {};
34
35template<class T>
36struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
37
38template<class T>
39struct is_shared_ptr<std::shared_ptr<T>&> : std::true_type {};
40
41template<class T>
42struct is_shared_ptr<const std::shared_ptr<T>&> : std::true_type {};
43
44template<class T>
45struct is_shared_ptr<std::shared_ptr<T>*> : std::true_type {};
46
47template<class T>
48struct is_shared_ptr<const std::shared_ptr<T>*> : std::true_type {};
49
50template<class T>
51struct is_unique_ptr : std::false_type {};
52
53template<class T>
54struct is_unique_ptr<std::unique_ptr<T>> : std::true_type {};
55
58{
59public:
60 virtual ~heap_arg_deleter_base() = default;
61
63};
64
66template<typename T>
68{
69public:
70 heap_arg_deleter(T& arg) : m_arg(arg) { }
71 virtual ~heap_arg_deleter() {
72 delete &m_arg;
73 }
74private:
75 T& m_arg;
76};
77
79template<typename T>
81{
82public:
83 heap_arg_deleter(T* arg) : m_arg(arg) { }
84 virtual ~heap_arg_deleter() {
85 delete m_arg;
86 }
87private:
88 T* m_arg;
89};
90
92template<typename T>
94{
95public:
96 heap_arg_deleter(T** arg) : m_arg(arg) {}
98 delete *m_arg;
99 delete m_arg;
100 }
101private:
102 T** m_arg;
103};
104
106template <typename Arg, typename... TupleElem>
107auto tuple_append(xlist<std::shared_ptr<heap_arg_deleter_base>>& heapArgs, const std::tuple<TupleElem...> &tup, Arg** arg)
108{
109 Arg** heap_arg = nullptr;
110
111 // Check if arg is nullptr or *arg is nullptr
112 if (arg != nullptr && *arg != nullptr) {
113 // Allocate memory for heap_arg and copy the value
114 heap_arg = new(std::nothrow) Arg * ();
115 if (!heap_arg) {
116 BAD_ALLOC();
117 }
118
119 *heap_arg = new(std::nothrow) Arg(**arg);
120 if (!*heap_arg) {
121 delete heap_arg;
122 BAD_ALLOC();
123 }
124 }
125 else {
126 // If arg is nullptr or *arg is nullptr, create heap_arg as nullptr
127 heap_arg = new(std::nothrow) Arg * (nullptr);
128 if (!heap_arg) {
129 BAD_ALLOC();
130 }
131 }
132 std::shared_ptr<heap_arg_deleter_base> deleter(new(std::nothrow) heap_arg_deleter<Arg**>(heap_arg));
133 if (!deleter) {
134 BAD_ALLOC();
135 }
136 try {
137 heapArgs.push_back(deleter);
138 return std::tuple_cat(tup, std::make_tuple(heap_arg));
139 }
140 catch (const std::bad_alloc&) {
141 BAD_ALLOC();
142 throw;
143 }
144}
145
147template <typename Arg, typename... TupleElem>
148auto tuple_append(xlist<std::shared_ptr<heap_arg_deleter_base>>& heapArgs, const std::tuple<TupleElem...> &tup, Arg* arg)
149{
150 Arg* heap_arg = nullptr;
151 if (arg != nullptr) {
152 heap_arg = new(std::nothrow) Arg(*arg); // Only create a new Arg if arg is not nullptr
153 if (!heap_arg) {
154 BAD_ALLOC();
155 }
156 }
157 std::shared_ptr<heap_arg_deleter_base> deleter(new(std::nothrow) heap_arg_deleter<Arg*>(heap_arg));
158 if (!deleter) {
159 BAD_ALLOC();
160 }
161 try {
162 heapArgs.push_back(deleter);
163 return std::tuple_cat(tup, std::make_tuple(heap_arg));
164 }
165 catch (const std::bad_alloc&) {
166 BAD_ALLOC();
167 throw;
168 }
169}
170
172template <typename Arg, typename... TupleElem>
173auto tuple_append(xlist<std::shared_ptr<heap_arg_deleter_base>>& heapArgs, const std::tuple<TupleElem...> &tup, Arg& arg)
174{
175 Arg* heap_arg = new(std::nothrow) Arg(arg);
176 if (!heap_arg) {
177 BAD_ALLOC();
178 }
179 std::shared_ptr<heap_arg_deleter_base> deleter(new(std::nothrow) heap_arg_deleter<Arg*>(heap_arg));
180 if (!deleter) {
181 BAD_ALLOC();
182 }
183 try {
184 heapArgs.push_back(deleter);
185
186 auto temp = std::make_tuple(std::forward_as_tuple(*heap_arg)); // Dereference heap_arg when creating tuple element
187 auto new_type = std::get<0>(temp);
188 return std::tuple_cat(tup, new_type);
189 }
190 catch (const std::bad_alloc&) {
191 BAD_ALLOC();
192 throw;
193 }
194}
195
202template<typename... Ts>
203auto make_tuple_heap(xlist<std::shared_ptr<heap_arg_deleter_base>>& heapArgs, std::tuple<Ts...> tup)
204{
205 return tup;
206}
207
224template<typename Arg1, typename... Args, typename... Ts>
225auto make_tuple_heap(xlist<std::shared_ptr<heap_arg_deleter_base>>& heapArgs, std::tuple<Ts...> tup, Arg1 arg1, Args... args)
226{
227 static_assert(!(
228 (is_shared_ptr<Arg1>::value && (std::is_lvalue_reference_v<Arg1> || std::is_pointer_v<Arg1>))),
229 "std::shared_ptr reference argument not allowed");
230 static_assert(!std::is_same<Arg1, void*>::value, "void* argument not allowed");
231
232 auto new_tup = tuple_append(heapArgs, tup, arg1);
233 return make_tuple_heap(heapArgs, new_tup, args...);
234}
235
236}
237
238#endif
Delegate library options header file.
#define XALLOCATOR
Definition DelegateOpt.h:46
std::list< T, Alloc > xlist
Definition DelegateOpt.h:40
#define BAD_ALLOC()
Definition DelegateOpt.h:22
heap_arg_deleter(T *arg)
Definition make_tuple_heap.h:83
virtual ~heap_arg_deleter()
Definition make_tuple_heap.h:84
heap_arg_deleter(T **arg)
Definition make_tuple_heap.h:96
virtual ~heap_arg_deleter()
Definition make_tuple_heap.h:97
Base class for all deleter's.
Definition make_tuple_heap.h:58
virtual ~heap_arg_deleter_base()=default
Frees heap memory for reference heap argument.
Definition make_tuple_heap.h:68
virtual ~heap_arg_deleter()
Definition make_tuple_heap.h:71
heap_arg_deleter(T &arg)
Definition make_tuple_heap.h:70
The delegate library namespace.
Definition Delegate.h:27
auto make_tuple_heap(xlist< std::shared_ptr< heap_arg_deleter_base > > &heapArgs, std::tuple< Ts... > tup)
Terminate the template metaprogramming argument loop. This function is called when there are no more ...
Definition make_tuple_heap.h:203
auto tuple_append(xlist< std::shared_ptr< heap_arg_deleter_base > > &heapArgs, const std::tuple< TupleElem... > &tup, Arg **arg)
Append a pointer to pointer argument to the tuple.
Definition make_tuple_heap.h:107
Definition make_tuple_heap.h:33
Definition make_tuple_heap.h:51