Constructs this multicast delegate without any value, same as init.
Constructs this multicast delegate with a singular delegate to call.
Constructs this multicast delegate with a given array of delegates. Does not duplicate the array, so future modifications might change the behavior of this delegate. It is recommended only to use this for @nogc compatibility.
ditto
Overloads ~= operator to call add.
Adds += operator support for C# code compatibility
Adds -= operator support for C# code compatibility
Converts this multicast delegate to a normal delegate. This is also used as alias this, so this multicast delegate can be passed as delegate argument to functions or be called directly.
Returns the delegates of this multicast.
Implementation: actually calls the delegates for this multicast delegate. This has no function attributes set on it, so it's not recommended to be called manually.
Implementation: takes _invokeImpl as a delegate and adds the function attributes of the wrapping delegate. This may be considered an unsafe operation, especially with future added attributes which could change the behavior of a function call. The ABI is that of a normal extern(D) T delegate(Args...) const @trusted which gets changed to all the attributes of the wrapping delegate.
Adds one or more delegates to this multicast delegate in order. Returns a reference to this instance.
Returns the delegates member with the magic access mask storage stripped away for normal usage.
Sets the delegates member and resets the magic copy bit.
Reassigns this multicast delegate to a single delegate. Returns a reference to this instance.
Reassigns this multicast delegate with a given array of delegates. Does not duplicate the array, so future modifications might change the behavior of this delegate. It is recommended only to use this for @nogc compatibility. Returns a reference to this instance.
Unsets this multicast delegate to the init state.
Overloads any binary operator (+, -, ~) to operate on a copy of this multicast delegate. Performs a duplication of the delegates array using the GC.
Checks if there are any delegates and if this can be called.
Removes a delegate from this multicast delegate. Returns a reference to this instance. Note that this will duplicate the array in case this delegate did not create it.
Removes a delegate from this multicast delegate, assumes this instance holds a unique reference to the delegates array. If this is called on copies of this multicast instance, change in behavior may occur.
the delegate or function pointer type which this MulticastImpl simulates. In case of function pointers this will be a delegate of the same return value, parameters and attributes.
if true, crash with assert(false) in case you try to call an instance with no delegates set.
int modify1(ref string[] stack) { stack ~= "1"; return cast(int) stack.length; } int modify2(ref string[] stack) { stack ~= "2"; return 9001; } string[] stack; // del is like a delegate now Multicast!(int delegate(ref string[])) del = &modify1; assert(del(stack) == 1); assert(stack == ["1"]); stack = null; del ~= &modify2; assert(del(stack) == 9001); assert(stack == ["1", "2"]); void someMethod(int delegate(ref string[]) fn) { } someMethod(del); someMethod(del);
Full multicast delegate implementation of this package. Modification operations are nothrow, pure, @safe and if possible @nogc. Using the @nogc overloads it's possible to use all functionality. Invocation inherits the attributes of the delegate or function pointer.
Even though the multicast implementation acts like a reference type, it is actually a value type and not a reference type, so modifications of copies will not be reflected in the source object. While normal copying by passing around the multicast delegate by value doesn't copy the underlying array data, this data structure will track copies and perform a copy on write whenever state is changed in a way that would affect other instances. Relies on GC to cleanup duplicated arrays.
When a multicast delegate is invoked (converted to a normal delegate and invoked), all methods are called in order. Reference parameters will be forwarded and passed sequentially to each method. Any changes in reference parameters are visible to the next method. When any of the methods throws an exception that is not caught within the method, that exception is passed to the caller of the delegate and no subsequent methods in the invocation list are called. If the delegate has a return value and/or out parameters, it returns the return value and parameters of the last method invoked.
Function attributes for delegates and function pointers are inherited to the simulated delegate. Function pointers are changed to being delegates however and the linkage of the delegate will be extern(D) as other linkage doesn't make sense for D delegates.
This is a lot like the MulticastDelegate type in C#, which performs the same operations. See
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/using-delegates
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/how-to-combine-delegates-multicast-delegates
https://docs.microsoft.com/en-us/dotnet/api/system.multicastdelegate?view=netcore-3.1
There are optional C#-style method overloads for + and - as well as an added GetInvocationList method which simply returns the delegates. To use these, compile the library with version = CSharpCompat;.