MulticastImpl

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;.

Constructors

this
this(typeof(null) )

Constructs this multicast delegate without any value, same as init.

this
this(Del one)

Constructs this multicast delegate with a singular delegate to call.

this
this(immutable(Del)[] all)
this(Del[] all)

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.

Postblit

this(this)
this(this)
Undocumented in source.

Alias This

toDelegate

ditto

Members

Aliases

opOpAssign
alias opOpAssign(string op : "~") = add

Overloads ~= operator to call add.

opOpAssign
alias opOpAssign(string op : "+") = add

Adds += operator support for C# code compatibility

opOpAssign
alias opOpAssign(string op : "-") = remove

Adds -= operator support for C# code compatibility

toDelegate
alias toDelegate = _invokePtr

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.

Functions

GetInvocationList
auto GetInvocationList()

Returns the delegates of this multicast.

_invokeImpl
ReturnType!Del _invokeImpl(Parameters!Del params)

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.

_invokePtr
auto _invokePtr()

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.

add
auto ref add(Del[] dels)
auto ref add(MulticastImpl!(Del, v) del)
auto ref add(Del del)

Adds one or more delegates to this multicast delegate in order. Returns a reference to this instance.

delegates
inout(Del[]) delegates()

Returns the delegates member with the magic access mask storage stripped away for normal usage.

delegates
auto ref delegates(Del[] all)

Sets the delegates member and resets the magic copy bit.

opAssign
auto ref opAssign(Del one)

Reassigns this multicast delegate to a single delegate. Returns a reference to this instance.

opAssign
auto ref opAssign(Del[] all)

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.

opAssign
auto ref opAssign(typeof(null) )

Unsets this multicast delegate to the init state.

opBinary
auto opBinary(T rhs)

Overloads any binary operator (+, -, ~) to operate on a copy of this multicast delegate. Performs a duplication of the delegates array using the GC.

opCast
bool opCast()

Checks if there are any delegates and if this can be called.

remove
auto ref remove(Del del)

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.

removeAssumeUnique
auto ref removeAssumeUnique(Del del)

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.

Unions

__anonymous
union __anonymous
Undocumented in source.

Parameters

Del

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.

assertIfNull

if true, crash with assert(false) in case you try to call an instance with no delegates set.

Examples

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);

Meta