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...)>;
103 using Function = ReturnType(ArgumentTypes...);
104
107 {
108 m_callbacks = std::make_shared<const std::list<Callback>>();
109 }
110
113 {}
114
116 MulticastDelegate(std::nullptr_t) : MulticastDelegate()
117 {}
118
121 MulticastDelegate(const MulticastDelegate& o)
122 : Details::DelegateHoldingVariables(o)
123 , m_callbacks(o.m_callbacks)
124 {}
125
128 MulticastDelegate& operator=(const MulticastDelegate& o)
129 {
130 if ( this == &o )
131 return *this;
132
133#ifdef ASPOSE_THREADSAFE_DELEGATES
134 std::lock(m_guard, o.m_guard);
135 std::lock_guard<std::recursive_mutex> l1( m_guard, std::adopt_lock );
136 std::lock_guard<std::recursive_mutex> l2(o.m_guard, std::adopt_lock);
137#endif
138 m_callbacks = o.m_callbacks;
139 Details::DelegateHoldingVariables::operator = (o);
140 return *this;
141 }
142
143 // movable
146 MulticastDelegate(MulticastDelegate&& o) noexcept
147 : Details::DelegateHoldingVariables(o)
148 , m_callbacks(std::move(o.m_callbacks))
149 {}
150
153 MulticastDelegate& operator=(MulticastDelegate&& o) noexcept
154 {
155 m_callbacks = std::move(o.m_callbacks);
156 Details::DelegateHoldingVariables::operator = (std::move(o));
157 return *this;
158 }
159
162 MulticastDelegate(Callback&& initial) : MulticastDelegate()
163 {
164 mutable_list()->push_back(std::move(initial));
165 }
166
170 template <class T, typename = decltype(Callback(std::declval<T>()))>
171 MulticastDelegate(T arg) : MulticastDelegate(Callback(arg))
172 {
173 }
174
177 MulticastDelegate(std::function<ReturnType(ArgumentTypes...)> arg) : MulticastDelegate(Callback(arg))
178 {
179 }
180
183 bool empty() const
184 {
185#ifdef ASPOSE_THREADSAFE_DELEGATES
186 std::lock_guard<std::recursive_mutex> lock(m_guard);
187#endif
188
189#ifdef ASPOSE_REMOVE_EMPTY_CALLBACKS
190 bool res = true;
191 if (m_callbacks)
192 {
193 for (auto it = m_callbacks->begin(); it != m_callbacks->end(); ++it)
194 res &= it->Empty();
195 }
196 return res;
197#else
198 return m_callbacks->empty();
199#endif
200 }
201
204 bool IsNull() const { return empty(); }
205
206 const TypeInfo& GetType() const
207 {
208 return Type();
209 }
210
212 {
213 return GetType().ToString();
214 }
215
216 int GetHashCode() const
217 {
218#ifdef ASPOSE_THREADSAFE_DELEGATES
219 std::lock_guard<std::recursive_mutex> lock(m_guard);
220#endif
221 return System::GetHashCode(m_callbacks.get());
222 }
223
224 bool Equals(const MulticastDelegate& other)
225 {
226 return *this == other;
227 }
228
231 bool operator==(const std::nullptr_t&) const
232 {
233 return empty();
234 }
235
238 bool operator!=(const std::nullptr_t&) const
239 {
240 return !operator==(nullptr);
241 }
242
246 MulticastDelegate& connect(Callback callback)
247 {
248#ifdef ASPOSE_THREADSAFE_DELEGATES
249 std::lock_guard<std::recursive_mutex> lock(m_guard);
250#endif
251
252 mutable_list()->push_back(std::move(callback));
253
254 return *this;
255 }
256
262 template <class R, class... Args>
263 MulticastDelegate& connect(std::function<R(Args...)> f)
264 {
265 return connect(Callback(f));
266 }
267
271 MulticastDelegate& connect(MulticastDelegate& other)
272 {
273 if (other.m_callbacks)
274 for (auto &callback : *other.m_callbacks)
275 connect(callback);
276 return *this;
277 }
278
285 template <class MemberType, class ClassType>
286 MulticastDelegate& connect(MemberType ClassType::* member, ClassType * obj)
287 {
288 CODEPORTING_DEBUG_ASSERT( obj != nullptr );
289 return connect(Callback(member, obj));
290 }
291
298 template <class MemberType, class ClassType>
299 MulticastDelegate& connect(MemberType ClassType::* member, const SharedPtr<ClassType> & obj)
300 {
301 CODEPORTING_DEBUG_ASSERT(obj != nullptr);
302 return connect(Callback(member, obj));
303 }
304
308 MulticastDelegate& operator +=(Callback callback)
309 {
310 return connect(std::move(callback));
311 }
312
316 MulticastDelegate& disconnect(Callback callback)
317 {
318#ifdef ASPOSE_THREADSAFE_DELEGATES
319 std::lock_guard<std::recursive_mutex> lock(m_guard);
320#endif
321 auto callbacks = mutable_list();
322 auto it = std::find_if(callbacks->rbegin(), callbacks->rend(), [&](const Callback& c){return callback == c;});
323 if (it != callbacks->rend())
324 callbacks->erase(std::next(it).base());
325 return *this;
326 }
327
334 template <class MemberType, class ClassType>
335 MulticastDelegate& disconnect(MemberType ClassType::* member, ClassType * obj)
336 {
337 CODEPORTING_DEBUG_ASSERT(obj != nullptr);
338 return disconnect(Callback(member, obj));
339 }
340
347 template <class MemberType, class ClassType>
348 MulticastDelegate& disconnect(MemberType ClassType::* member, const SharedPtr<ClassType> & obj)
349 {
350 CODEPORTING_DEBUG_ASSERT(obj != nullptr);
351 return disconnect(Callback(member, obj));
352 }
353
357 MulticastDelegate& disconnect(MulticastDelegate& other)
358 {
359 if (other.m_callbacks)
360 {
361#ifdef ASPOSE_THREADSAFE_DELEGATES
362 std::lock(m_guard, o.m_guard);
363 std::lock_guard<std::recursive_mutex> l1(m_guard, std::adopt_lock);
364 std::lock_guard<std::recursive_mutex> l2(o.m_guard, std::adopt_lock);
365#endif
366 for (auto &callback : *other.m_callbacks)
367 disconnect(callback);
368 }
369 return *this;
370 }
371
375 MulticastDelegate& operator -=(Callback callback)
376 {
377 return disconnect(std::move(callback));
378 }
379
383 bool operator == (const MulticastDelegate& other) const
384 {
385 CODEPORTING_DEBUG_ASSERT(m_callbacks != nullptr && other.m_callbacks != nullptr);
386
387 // If both delegates point to same callback list - they are equal for sure
388 if (m_callbacks == other.m_callbacks)
389 return true;
390
391 // Then compare all callbacks one for another
392 return *m_callbacks == *other.m_callbacks;
393 }
394
398 bool operator != (const MulticastDelegate& other) const
399 {
400 return !operator == (other);
401 }
402
405 MulticastDelegate& disconnect_all_slots()
406 {
407#ifdef ASPOSE_THREADSAFE_DELEGATES
408 std::lock_guard<std::recursive_mutex> lock(m_guard);
409#endif
410 mutable_list()->clear();
411
412 return *this;
413 }
414
417 {
418 if (m_callbacks && !m_callbacks->empty())
419 {
420 // We don't need to get unique callbacks here, because even shared callbacks, if empty, are subject to cleanup.
421 auto* mutable_callbacks = const_cast<std::list<Callback>*>(m_callbacks.get());
422
423 for (auto it = mutable_callbacks->begin(); it != mutable_callbacks->end();)
424 {
425 if (it->Empty())
426 it = mutable_callbacks->erase(it);
427 else
428 ++it;
429 }
430 }
431 }
432
436 ReturnType invoke(ArgumentTypes... args) const
437 {
438#ifdef ASPOSE_THREADSAFE_DELEGATES
439 std::lock_guard<std::recursive_mutex> lock(m_guard);
440#endif
441
442#ifdef ASPOSE_REMOVE_EMPTY_CALLBACKS
443 remove_empty_callbacks();
444#endif
445 if (m_callbacks && !m_callbacks->empty())
446 {
447 auto callbacks_copy = m_callbacks; // we must save the current callbacks list in case it will be changed during the call
448 auto last = std::prev(callbacks_copy->end()); // always valid, m_callbacks is not empty
449 for (auto it = callbacks_copy->begin(); it != last; ++it)
450 (*it)(args...); // ignore result!
451
452 return (*last)(args...);
453 }
454
455 throw NullReferenceException(u"MulticastDelegate: Object reference not set to an instance of an object.");
456 }
457
461 ReturnType operator()(ArgumentTypes... args) const
462 {
463 return invoke(args...);
464 }
465
467 static const TypeInfo& Type()
468 {
469 return *static_holder<ThisTypeInfo>();
470 }
471
472
475 template <typename CallbackArgumentType>
476 SharedPtr<IAsyncResult> BeginInvoke(ArgumentTypes... args, const AsyncCallback& member, const CallbackArgumentType& obj)
477 {
478 throw System::NotImplementedException(ASPOSE_CURRENT_FUNCTION);
479 }
480
484 {
485 throw System::NotImplementedException(ASPOSE_CURRENT_FUNCTION);
486 }
487
488#if defined(ASPOSE_GET_SHARED_MEMBERS) || defined(__DBG_FOR_EACH_MEMBER)
490 std::shared_ptr<Details::HeldVariables> GetHeldVariables() const
491 {
492 auto heldVariables = std::make_shared<Details::HeldVariables>();
493
494 heldVariables->CopyFrom(m_heldVariables);
495
496 if (m_callbacks && !m_callbacks->empty())
497 {
498 for (auto it = m_callbacks->cbegin(); it != m_callbacks->cend(); ++it)
499 {
500 heldVariables->CopyFrom(it->GetHeldVariables());
501 }
502 }
503
504 return heldVariables;
505 }
506#endif
507
508 private:
511 std::list<Callback>* mutable_list()
512 {
513 CODEPORTING_DEBUG_ASSERT(m_callbacks != nullptr);
514
515 if (m_callbacks.use_count() > 1)
516 m_callbacks = std::make_shared<std::list<Callback>>(*m_callbacks);
517
518 return const_cast<std::list<Callback>*>(m_callbacks.get());
519 }
520
522 mutable std::shared_ptr<const std::list<Callback>> m_callbacks;
523
524#ifdef ASPOSE_THREADSAFE_DELEGATES
526 mutable std::recursive_mutex m_guard;
527#endif
528 };
529
534 template <typename T>
535 MulticastDelegate<T> operator+(MulticastDelegate<T> lhv, MulticastDelegate<T> rhv)
536 {
537 return lhv.connect(rhv);
538 }
539
544 template <typename T>
545 MulticastDelegate<T> operator-(MulticastDelegate<T> lhv, MulticastDelegate<T> rhv)
546 {
547 return lhv.disconnect(rhv);
548 }
549
552 template <typename TTo> struct CastResult;
553
556 template <typename T>
557 struct ASPOSECPP_SHARED_CLASS CastResult<MulticastDelegate<T>>
558 {
560 typedef MulticastDelegate<T> type;
561 };
562
563 template <class T>
564 struct IsBoxable<MulticastDelegate<T>> : std::true_type
565 {
566 };
568
569} // namespace System
570#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:271
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:348
MulticastDelegate(MulticastDelegate &&o) noexcept
Moving constructor.
Definition: multicast_delegate.h:146
bool operator!=(const std::nullptr_t &) const
Determines whether the delegate collection is not empty.
Definition: multicast_delegate.h:238
bool empty() const
Determines whether the delegate collection is empty.
Definition: multicast_delegate.h:183
ReturnType operator()(ArgumentTypes... args) const
Invokes all delegates currently present in the delegates collection. Delegates are invoked in the sam...
Definition: multicast_delegate.h:461
MulticastDelegate & operator=(const MulticastDelegate &o)
Assigns the collection of delegates represented by the specified object to the current object....
Definition: multicast_delegate.h:128
bool IsNull() const
Determines whether the delegate collection is empty.
Definition: multicast_delegate.h:204
MulticastDelegate & disconnect(MulticastDelegate &other)
Removes the specified MulticastDelegate object from the delegate collection.
Definition: multicast_delegate.h:357
MulticastDelegate & operator=(MulticastDelegate &&o) noexcept
Moving assignment operator.
Definition: multicast_delegate.h:153
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:299
MulticastDelegate & disconnect(Callback callback)
Removes the specified delegate from the delegate collection.
Definition: multicast_delegate.h:316
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:335
MulticastDelegate(const MulticastDelegate &o)
Performs a shallow copy of the delegate collection.
Definition: multicast_delegate.h:121
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:286
ReturnType EndInvoke(const SharedPtr< IAsyncResult > &)
NOT IMPLEMENTED.
Definition: multicast_delegate.h:483
MulticastDelegate(Callback &&initial)
Constructs an instance and puts the specified delegate to the delegates collection.
Definition: multicast_delegate.h:162
String ToString() const
Definition: multicast_delegate.h:211
MulticastDelegate(T arg)
Constructs an instance and puts the specified value to the delegates collection.
Definition: multicast_delegate.h:171
ReturnType invoke(ArgumentTypes... args) const
Invokes all delegates currently present in the delegates collection. Delegates are invoked in the sam...
Definition: multicast_delegate.h:436
static const TypeInfo & Type()
Returns a reference to the TypeInfo object representing the MulticastDelegate class type information.
Definition: multicast_delegate.h:467
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:263
MulticastDelegate & disconnect_all_slots()
Removes all delegates from the delegate collection.
Definition: multicast_delegate.h:405
~MulticastDelegate()
Destructor.
Definition: multicast_delegate.h:112
MulticastDelegate & connect(Callback callback)
Adds the specified delegate to the collection.
Definition: multicast_delegate.h:246
MulticastDelegate(std::function< ReturnType(ArgumentTypes...)> arg)
Constructs an instance and puts the specified value to the delegates collection.
Definition: multicast_delegate.h:177
const TypeInfo & GetType() const
Definition: multicast_delegate.h:206
MulticastDelegate()
Constructs an empty collection.
Definition: multicast_delegate.h:106
bool Equals(const MulticastDelegate &other)
Definition: multicast_delegate.h:224
int GetHashCode() const
Definition: multicast_delegate.h:216
void remove_empty_callbacks() const
Cleans out contained callbacks that are empty (not actually calling anything).
Definition: multicast_delegate.h:416
bool operator==(const std::nullptr_t &) const
Determines whether the delegate collection is empty.
Definition: multicast_delegate.h:231
MulticastDelegate(std::nullptr_t)
Equivalent to defalt constructor.
Definition: multicast_delegate.h:116
ReturnType(ArgumentTypes...) Function
The type of the function related to delegate signature.
Definition: multicast_delegate.h:103
SharedPtr< IAsyncResult > BeginInvoke(ArgumentTypes... args, const AsyncCallback &member, const CallbackArgumentType &obj)
NOT IMPLEMENTED.
Definition: multicast_delegate.h:476
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:125
String ToString() const
Wrapper for handling String class in contexts where ToString() is being called on value type objects.
Definition: string.h:512
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:156
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:150
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