CodePorting.Translator Cs2Cpp
CodePorting.Translator.Cs2Cpp.Framework
multicast_delegate.h
1
3#ifndef _aspose_system_multicast_delegate_h_
4#define _aspose_system_multicast_delegate_h_
5
6#include "delegate.h"
7#include "shared_ptr.h"
8#include "exceptions.h"
9#include "system/details/delegate_holding_variables.h"
10#include <list>
11#include <functional>
12#include <algorithm>
13#include <type_traits>
14#include <utility>
15
16#define ASPOSE_REMOVE_EMPTY_CALLBACKS
17
18#ifdef ASPOSE_THREADSAFE_DELEGATES
19#include <mutex>
20#endif
21
22namespace System
23{
24 class IAsyncResult;
25
27 template<class Unused>
28 class MulticastDelegate;
30
31 using AsyncCallback = MulticastDelegate<void(SharedPtr<IAsyncResult>)>;
32
35 {
38 : TypeInfoPtr(u"System::MulticastDelegate")
39 {}
40 };
41
93 template <class ReturnType, class... ArgumentTypes>
94 class ASPOSECPP_SHARED_CLASS MulticastDelegate<ReturnType(ArgumentTypes...)> : public Details::DelegateHoldingVariables
95 {
96 private:
98
99 public:
101 using Callback = Delegate<ReturnType(ArgumentTypes...)>;
102
105 {
106 m_callbacks = std::make_shared<const std::list<Callback>>();
107 }
108
111 {}
112
114 MulticastDelegate(std::nullptr_t) : MulticastDelegate()
115 {}
116
119 MulticastDelegate(const MulticastDelegate& o)
120 : Details::DelegateHoldingVariables(o)
121 , m_callbacks(o.m_callbacks)
122 {}
123
126 MulticastDelegate& operator=(const MulticastDelegate& o)
127 {
128 if ( this == &o )
129 return *this;
130
131#ifdef ASPOSE_THREADSAFE_DELEGATES
132 std::lock(m_guard, o.m_guard);
133 std::lock_guard<std::recursive_mutex> l1( m_guard, std::adopt_lock );
134 std::lock_guard<std::recursive_mutex> l2(o.m_guard, std::adopt_lock);
135#endif
136 m_callbacks = o.m_callbacks;
137 Details::DelegateHoldingVariables::operator = (o);
138 return *this;
139 }
140
141 // movable
144 MulticastDelegate(MulticastDelegate&& o) noexcept
145 : Details::DelegateHoldingVariables(o)
146 , m_callbacks(std::move(o.m_callbacks))
147 {}
148
151 MulticastDelegate& operator=(MulticastDelegate&& o) noexcept
152 {
153 m_callbacks = std::move(o.m_callbacks);
154 Details::DelegateHoldingVariables::operator = (std::move(o));
155 return *this;
156 }
157
160 MulticastDelegate(Callback&& initial) : MulticastDelegate()
161 {
162 mutable_list()->push_back(std::move(initial));
163 }
164
168 template <class T, typename = decltype(Callback(std::declval<T>()))>
169 MulticastDelegate(T arg) : MulticastDelegate(Callback(arg))
170 {
171 }
172
175 MulticastDelegate(std::function<ReturnType(ArgumentTypes...)> arg) : MulticastDelegate(Callback(arg))
176 {
177 }
178
181 bool empty() const
182 {
183#ifdef ASPOSE_THREADSAFE_DELEGATES
184 std::lock_guard<std::recursive_mutex> lock(m_guard);
185#endif
186
187#ifdef ASPOSE_REMOVE_EMPTY_CALLBACKS
188 bool res = true;
189 if (m_callbacks)
190 {
191 for (auto it = m_callbacks->begin(); it != m_callbacks->end(); ++it)
192 res &= it->Empty();
193 }
194 return res;
195#else
196 return m_callbacks->empty();
197#endif
198 }
199
202 bool IsNull() const { return empty(); }
203
204 const TypeInfo& GetType() const
205 {
206 return Type();
207 }
208
210 {
211 return GetType().ToString();
212 }
213
214 int GetHashCode() const
215 {
216#ifdef ASPOSE_THREADSAFE_DELEGATES
217 std::lock_guard<std::recursive_mutex> lock(m_guard);
218#endif
219 return System::GetHashCode(m_callbacks.get());
220 }
221
224 bool operator==(const std::nullptr_t&) const
225 {
226 return empty();
227 }
228
231 bool operator!=(const std::nullptr_t&) const
232 {
233 return !operator==(nullptr);
234 }
235
239 MulticastDelegate& connect(Callback callback)
240 {
241#ifdef ASPOSE_THREADSAFE_DELEGATES
242 std::lock_guard<std::recursive_mutex> lock(m_guard);
243#endif
244
245 mutable_list()->push_back(std::move(callback));
246
247 return *this;
248 }
249
255 template <class R, class... Args>
256 MulticastDelegate& connect(std::function<R(Args...)> f)
257 {
258 return connect(Callback(f));
259 }
260
264 MulticastDelegate& connect(MulticastDelegate& other)
265 {
266 if (other.m_callbacks)
267 for (auto &callback : *other.m_callbacks)
268 connect(callback);
269 return *this;
270 }
271
278 template <class MemberType, class ClassType>
279 MulticastDelegate& connect(MemberType ClassType::* member, ClassType * obj)
280 {
281 CODEPORTING_DEBUG_ASSERT( obj != nullptr );
282 return connect(Callback(member, obj));
283 }
284
291 template <class MemberType, class ClassType>
292 MulticastDelegate& connect(MemberType ClassType::* member, const SharedPtr<ClassType> & obj)
293 {
294 CODEPORTING_DEBUG_ASSERT(obj != nullptr);
295 return connect(Callback(member, obj));
296 }
297
301 MulticastDelegate& operator +=(Callback callback)
302 {
303 return connect(std::move(callback));
304 }
305
309 MulticastDelegate& disconnect(Callback callback)
310 {
311#ifdef ASPOSE_THREADSAFE_DELEGATES
312 std::lock_guard<std::recursive_mutex> lock(m_guard);
313#endif
314 auto callbacks = mutable_list();
315 auto it = std::find_if(callbacks->rbegin(), callbacks->rend(), [&](const Callback& c){return callback == c;});
316 if (it != callbacks->rend())
317 callbacks->erase(std::next(it).base());
318 return *this;
319 }
320
327 template <class MemberType, class ClassType>
328 MulticastDelegate& disconnect(MemberType ClassType::* member, ClassType * obj)
329 {
330 CODEPORTING_DEBUG_ASSERT(obj != nullptr);
331 return disconnect(Callback(member, obj));
332 }
333
340 template <class MemberType, class ClassType>
341 MulticastDelegate& disconnect(MemberType ClassType::* member, const SharedPtr<ClassType> & obj)
342 {
343 CODEPORTING_DEBUG_ASSERT(obj != nullptr);
344 return disconnect(Callback(member, obj));
345 }
346
350 MulticastDelegate& disconnect(MulticastDelegate& other)
351 {
352 if (other.m_callbacks)
353 {
354#ifdef ASPOSE_THREADSAFE_DELEGATES
355 std::lock(m_guard, o.m_guard);
356 std::lock_guard<std::recursive_mutex> l1(m_guard, std::adopt_lock);
357 std::lock_guard<std::recursive_mutex> l2(o.m_guard, std::adopt_lock);
358#endif
359 for (auto &callback : *other.m_callbacks)
360 disconnect(callback);
361 }
362 return *this;
363 }
364
368 MulticastDelegate& operator -=(Callback callback)
369 {
370 return disconnect(std::move(callback));
371 }
372
376 bool operator == (const MulticastDelegate& other) const
377 {
378 CODEPORTING_DEBUG_ASSERT(m_callbacks != nullptr && other.m_callbacks != nullptr);
379
380 // If both delegates point to same callback list - they are equal for sure
381 if (m_callbacks == other.m_callbacks)
382 return true;
383
384 // Then compare all callbacks one for another
385 return *m_callbacks == *other.m_callbacks;
386 }
387
391 bool operator != (const MulticastDelegate& other) const
392 {
393 return !operator == (other);
394 }
395
398 MulticastDelegate& disconnect_all_slots()
399 {
400#ifdef ASPOSE_THREADSAFE_DELEGATES
401 std::lock_guard<std::recursive_mutex> lock(m_guard);
402#endif
403 mutable_list()->clear();
404
405 return *this;
406 }
407
410 {
411 if (m_callbacks && !m_callbacks->empty())
412 {
413 // We don't need to get unique callbacks here, because even shared callbacks, if empty, are subject to cleanup.
414 auto* mutable_callbacks = const_cast<std::list<Callback>*>(m_callbacks.get());
415
416 for (auto it = mutable_callbacks->begin(); it != mutable_callbacks->end();)
417 {
418 if (it->Empty())
419 it = mutable_callbacks->erase(it);
420 else
421 ++it;
422 }
423 }
424 }
425
429 ReturnType invoke(ArgumentTypes... args) const
430 {
431#ifdef ASPOSE_THREADSAFE_DELEGATES
432 std::lock_guard<std::recursive_mutex> lock(m_guard);
433#endif
434
435#ifdef ASPOSE_REMOVE_EMPTY_CALLBACKS
436 remove_empty_callbacks();
437#endif
438 if (m_callbacks && !m_callbacks->empty())
439 {
440 auto callbacks_copy = m_callbacks; // we must save the current callbacks list in case it will be changed during the call
441 auto last = std::prev(callbacks_copy->end()); // always valid, m_callbacks is not empty
442 for (auto it = callbacks_copy->begin(); it != last; ++it)
443 (*it)(args...); // ignore result!
444
445 return (*last)(args...);
446 }
447
448 throw NullReferenceException(u"MulticastDelegate: Object reference not set to an instance of an object.");
449 }
450
454 ReturnType operator()(ArgumentTypes... args) const
455 {
456 return invoke(args...);
457 }
458
460 static const TypeInfo& Type()
461 {
462 return *static_holder<ThisTypeInfo>();
463 }
464
465
468 template <typename CallbackArgumentType>
469 SharedPtr<IAsyncResult> BeginInvoke(ArgumentTypes... args, const AsyncCallback& member, const CallbackArgumentType& obj)
470 {
471 throw System::NotImplementedException(ASPOSE_CURRENT_FUNCTION);
472 }
473
477 {
478 throw System::NotImplementedException(ASPOSE_CURRENT_FUNCTION);
479 }
480
481#if defined(ASPOSE_GET_SHARED_MEMBERS) || defined(__DBG_FOR_EACH_MEMBER)
483 std::shared_ptr<Details::HeldVariables> GetHeldVariables() const
484 {
485 auto heldVariables = std::make_shared<Details::HeldVariables>();
486
487 heldVariables->CopyFrom(m_heldVariables);
488
489 if (m_callbacks && !m_callbacks->empty())
490 {
491 for (auto it = m_callbacks->cbegin(); it != m_callbacks->cend(); ++it)
492 {
493 heldVariables->CopyFrom(it->GetHeldVariables());
494 }
495 }
496
497 return heldVariables;
498 }
499#endif
500
501 private:
504 std::list<Callback>* mutable_list()
505 {
506 CODEPORTING_DEBUG_ASSERT(m_callbacks != nullptr);
507
508 if (m_callbacks.use_count() > 1)
509 m_callbacks = std::make_shared<std::list<Callback>>(*m_callbacks);
510
511 return const_cast<std::list<Callback>*>(m_callbacks.get());
512 }
513
515 mutable std::shared_ptr<const std::list<Callback>> m_callbacks;
516
517#ifdef ASPOSE_THREADSAFE_DELEGATES
519 mutable std::recursive_mutex m_guard;
520#endif
521 };
522
527 template <typename T>
528 MulticastDelegate<T> operator+(MulticastDelegate<T> lhv, MulticastDelegate<T> rhv)
529 {
530 return lhv.connect(rhv);
531 }
532
537 template <typename T>
538 MulticastDelegate<T> operator-(MulticastDelegate<T> lhv, MulticastDelegate<T> rhv)
539 {
540 return lhv.disconnect(rhv);
541 }
542
545 template <typename TTo> struct CastResult;
546
549 template <typename T>
550 struct ASPOSECPP_SHARED_CLASS CastResult<MulticastDelegate<T>>
551 {
553 typedef MulticastDelegate<T> type;
554 };
555
556 template <class T>
557 struct IsBoxable<MulticastDelegate<T>> : std::true_type
558 {
559 };
561
562} // namespace System
563#endif // _aspose_system_multicast_delegate_h_
Represents a pointer to a function, method or a function object. This type should be allocated on sta...
Definition: delegate.h:56
MulticastDelegate & connect(MulticastDelegate &other)
Adds the specified MulticastDelegate object to the delegate collection.
Definition: multicast_delegate.h:264
MulticastDelegate & disconnect(MemberType ClassType::*member, const SharedPtr< ClassType > &obj)
Removes the specified non-static method of the specified object from the delegate collection.
Definition: multicast_delegate.h:341
MulticastDelegate(MulticastDelegate &&o) noexcept
Moving constructor.
Definition: multicast_delegate.h:144
bool operator!=(const std::nullptr_t &) const
Determines whether the delegate collection is not empty.
Definition: multicast_delegate.h:231
bool empty() const
Determines whether the delegate collection is empty.
Definition: multicast_delegate.h:181
ReturnType operator()(ArgumentTypes... args) const
Invokes all delegates currently present in the delegates collection. Delegates are invoked in the sam...
Definition: multicast_delegate.h:454
MulticastDelegate & operator=(const MulticastDelegate &o)
Assigns the collection of delegates represented by the specified object to the current object....
Definition: multicast_delegate.h:126
bool IsNull() const
Determines whether the delegate collection is empty.
Definition: multicast_delegate.h:202
MulticastDelegate & disconnect(MulticastDelegate &other)
Removes the specified MulticastDelegate object from the delegate collection.
Definition: multicast_delegate.h:350
MulticastDelegate & operator=(MulticastDelegate &&o) noexcept
Moving assignment operator.
Definition: multicast_delegate.h:151
MulticastDelegate & connect(MemberType ClassType::*member, const SharedPtr< ClassType > &obj)
Adds the specified non-static method of the specified object to the delegate collection.
Definition: multicast_delegate.h:292
MulticastDelegate & disconnect(Callback callback)
Removes the specified delegate from the delegate collection.
Definition: multicast_delegate.h:309
MulticastDelegate & disconnect(MemberType ClassType::*member, ClassType *obj)
Removes the specified non-static method of the specified object from the delegate collection.
Definition: multicast_delegate.h:328
MulticastDelegate(const MulticastDelegate &o)
Performs a shallow copy of the delegate collection.
Definition: multicast_delegate.h:119
MulticastDelegate & connect(MemberType ClassType::*member, ClassType *obj)
Adds the specified non-static method of the specified object to the delegate collection.
Definition: multicast_delegate.h:279
ReturnType EndInvoke(const SharedPtr< IAsyncResult > &)
NOT IMPLEMENTED.
Definition: multicast_delegate.h:476
MulticastDelegate(Callback &&initial)
Constructs an instance and puts the specified delegate to the delegates collection.
Definition: multicast_delegate.h:160
String ToString() const
Definition: multicast_delegate.h:209
MulticastDelegate(T arg)
Constructs an instance and puts the specified value to the delegates collection.
Definition: multicast_delegate.h:169
ReturnType invoke(ArgumentTypes... args) const
Invokes all delegates currently present in the delegates collection. Delegates are invoked in the sam...
Definition: multicast_delegate.h:429
static const TypeInfo & Type()
Returns a reference to the TypeInfo object representing the MulticastDelegate class type information.
Definition: multicast_delegate.h:460
MulticastDelegate & connect(std::function< R(Args...)> f)
Adds the specified function object to the delegate collection. The function object is converted to th...
Definition: multicast_delegate.h:256
MulticastDelegate & disconnect_all_slots()
Removes all delegates from the delegate collection.
Definition: multicast_delegate.h:398
~MulticastDelegate()
Destructor.
Definition: multicast_delegate.h:110
MulticastDelegate & connect(Callback callback)
Adds the specified delegate to the collection.
Definition: multicast_delegate.h:239
MulticastDelegate(std::function< ReturnType(ArgumentTypes...)> arg)
Constructs an instance and puts the specified value to the delegates collection.
Definition: multicast_delegate.h:175
const TypeInfo & GetType() const
Definition: multicast_delegate.h:204
MulticastDelegate()
Constructs an empty collection.
Definition: multicast_delegate.h:104
int GetHashCode() const
Definition: multicast_delegate.h:214
void remove_empty_callbacks() const
Cleans out contained callbacks that are empty (not actually calling anything).
Definition: multicast_delegate.h:409
bool operator==(const std::nullptr_t &) const
Determines whether the delegate collection is empty.
Definition: multicast_delegate.h:224
MulticastDelegate(std::nullptr_t)
Equivalent to defalt constructor.
Definition: multicast_delegate.h:114
SharedPtr< IAsyncResult > BeginInvoke(ArgumentTypes... args, const AsyncCallback &member, const CallbackArgumentType &obj)
NOT IMPLEMENTED.
Definition: multicast_delegate.h:469
Pointer class to wrap types being allocated on heap. Use it to manage memory for classes inheriting O...
Definition: smart_ptr.h:180
String class used across the library. Is a substitute for C# System.String when translating code....
Definition: string.h:122
String ToString() const
Wrapper for handling String class in contexts where ToString() is being called on value type objects.
Definition: string.h:494
Represents a particular type and provides information about it.
Definition: type_info.h:109
Definition: db_command.h:9
System::MulticastDelegate< void(SharedPtr< IAsyncResult >)> AsyncCallback
A delegate type that represents a method to be called when asynchronous operation completes.
Definition: async_callback.h:13
bool operator!=(ArraySegment< T > a, ArraySegment< T > b)
Definition: array_segment.h:157
Decimal operator+(const T &x, const Decimal &d)
Returns a new instance of Decimal class that represents a value that is a sum of the specified value ...
Definition: decimal.h:542
auto operator-(DayOfWeek a, DayOfWeek b)
Calculates the number of days between two days of week.
Definition: day_of_week.h:25
std::enable_if< std::is_scalar< T >::value, int >::type GetHashCode(const T &obj)
Returns a hash code for the specified scalar value.
Definition: get_hash_code.h:21
bool operator==(ArraySegment< T > a, ArraySegment< T > b)
Definition: array_segment.h:151
Represents a pointer to TypeInfo object that contains information about MulticastDelegate class.
Definition: multicast_delegate.h:35
MulticastDelegateTypeInfo()
Constructs an instance of MulticastDelegateTypeInfo class.
Definition: multicast_delegate.h:37
Wrapper for a pointer to an instance of TypeInfo class. This type should be allocated on stack and pa...
Definition: type_info.h:72