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 delete* heap_arg;
135 delete heap_arg;
136 BAD_ALLOC();
137 }
138 try {
139 heapArgs.push_back(deleter);
140 return std::tuple_cat(tup, std::make_tuple(heap_arg));
141 }
142 catch (const std::bad_alloc&) {
143 BAD_ALLOC();
144 throw;
145 }
146}
147
149template <typename Arg, typename... TupleElem>
150auto tuple_append(xlist<std::shared_ptr<heap_arg_deleter_base>>& heapArgs, const std::tuple<TupleElem...> &tup, Arg* arg)
151{
152 Arg* heap_arg = nullptr;
153 if (arg != nullptr) {
154 heap_arg = new(std::nothrow) Arg(*arg); // Only create a new Arg if arg is not nullptr
155 if (!heap_arg) {
156 BAD_ALLOC();
157 }
158 }
159 std::shared_ptr<heap_arg_deleter_base> deleter(new(std::nothrow) heap_arg_deleter<Arg*>(heap_arg));
160 if (!deleter) {
161 delete heap_arg;
162 BAD_ALLOC();
163 }
164 try {
165 heapArgs.push_back(deleter);
166 return std::tuple_cat(tup, std::make_tuple(heap_arg));
167 }
168 catch (const std::bad_alloc&) {
169 BAD_ALLOC();
170 throw;
171 }
172}
173
175template <typename Arg, typename... TupleElem>
176auto tuple_append(xlist<std::shared_ptr<heap_arg_deleter_base>>& heapArgs, const std::tuple<TupleElem...> &tup, Arg& arg)
177{
178 Arg* heap_arg = new(std::nothrow) Arg(arg);
179 if (!heap_arg) {
180 BAD_ALLOC();
181 }
182 std::shared_ptr<heap_arg_deleter_base> deleter(new(std::nothrow) heap_arg_deleter<Arg*>(heap_arg));
183 if (!deleter) {
184 delete heap_arg;
185 BAD_ALLOC();
186 }
187 try {
188 heapArgs.push_back(deleter);
189
190 auto temp = std::make_tuple(std::forward_as_tuple(*heap_arg)); // Dereference heap_arg when creating tuple element
191 auto new_type = std::get<0>(temp);
192 return std::tuple_cat(tup, new_type);
193 }
194 catch (const std::bad_alloc&) {
195 BAD_ALLOC();
196 throw;
197 }
198}
199
206template<typename... Ts>
207auto make_tuple_heap(xlist<std::shared_ptr<heap_arg_deleter_base>>& heapArgs, std::tuple<Ts...> tup)
208{
209 return tup;
210}
211
228template<typename Arg1, typename... Args, typename... Ts>
229auto make_tuple_heap(xlist<std::shared_ptr<heap_arg_deleter_base>>& heapArgs, std::tuple<Ts...> tup, Arg1 arg1, Args... args)
230{
231 static_assert(!(
232 (is_shared_ptr<Arg1>::value && (std::is_lvalue_reference_v<Arg1> || std::is_pointer_v<Arg1>))),
233 "std::shared_ptr reference argument not allowed");
234 static_assert(!std::is_same<Arg1, void*>::value, "void* argument not allowed");
235
236 auto new_tup = tuple_append(heapArgs, tup, arg1);
237 return make_tuple_heap(heapArgs, new_tup, args...);
238}
239
240}
241
242#endif
Delegate library options header file.
#define XALLOCATOR
Definition DelegateOpt.h:45
#define BAD_ALLOC()
Definition DelegateOpt.h:26
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
Definition DelegateOpt.h:49
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:207
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