Last active
November 4, 2016 20:15
-
-
Save NickStrupat/cadf7e3ea5ae1b8165e17629df2dc64a to your computer and use it in GitHub Desktop.
Event delegate contravariance
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private ImmutableArray<THandler> handlers = ImmutableArray<THandler>.Empty; | |
internal static void Add<THandler>(ref ImmutableArray<Action<THandler>> handlers, Action<THandler> handler) { | |
if (handler == null) | |
return; | |
ImmutableArray<Action<THandler>> initial, computed; | |
do { | |
initial = InterlockedGet(ref handlers); | |
computed = initial.Add(handler); | |
} | |
while (initial != ImmutableInterlocked.InterlockedCompareExchange(ref handlers, computed, initial)); | |
} | |
internal static void Remove<THandler>(ref ImmutableArray<Action<THandler>> handlers, Action<THandler> handler) { | |
if (handler == null) | |
return; | |
ImmutableArray<Action<THandler>> initial, computed; | |
do { | |
initial = InterlockedGet(ref handlers); | |
computed = RemoveLast(initial, handler); | |
} | |
while (initial != ImmutableInterlocked.InterlockedCompareExchange(ref handlers, computed, initial)); | |
} | |
private static void Raise<THandler>(ref ImmutableArray<Action<THandler>> handlers, THandler entry) { | |
var latestHandlers = InterlockedGet(ref handlers); | |
for (var i = 0; i < latestHandlers.Length; i++) | |
latestHandlers[i].Invoke(entry); | |
} | |
private static ImmutableArray<Action<THandler>> InterlockedGet<THandler>(ref ImmutableArray<Action<THandler>> handlers) { | |
return ImmutableInterlocked.InterlockedCompareExchange(ref handlers, ImmutableArray<Action<THandler>>.Empty, ImmutableArray<Action<THandler>>.Empty); | |
} | |
private static ImmutableArray<TDelegate> RemoveLast(ImmutableArray<TDelegate> source, TDelegate value) { | |
var list = source; | |
var index = list.LastIndexOf(value); | |
if (index >= 0) | |
return list.RemoveAt(index); | |
return list; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment