private static XChannel AddXChannel(LinkedList <XChannel> list, ChannelIdentification identification, object?targetId, bool exclusiveChannel, IWeakDelegate weakDelegate) { // lock (cs) required. if (exclusiveChannel) { if (list.Count > 0) { // other channel already exists. throw new InvalidOperationException(); } } else { if (list.First?.Value.ExclusiveChannel == true) { // Exclusive channel exists. throw new InvalidOperationException(); } } // New XChannel var channel = new XChannel(identification, targetId, exclusiveChannel, weakDelegate); // list: Identification to XChannels. channel.Node = list.AddLast(channel); return(channel); }
private static XChannel[] PrepareXChannelArray(LinkedList <XChannel> list, object?targetId) { // lock (cs) required. Convert LinkedList to Array, release garbage collected object, and increment reference count. var array = new XChannel[list.Count]; var arrayCount = 0; var node = list.First; LinkedListNode <XChannel>?nextNode; if (targetId == null) { while (node != null) { nextNode = node.Next; if (node.Value.IsAlive) {// The instance is still alive. array[arrayCount++] = node.Value; } else if (node.Value.ReferenceCount == 0) {// The instance is garbage collected and reference count is 0. CloseChannel(node.Value); } node = nextNode; } } else { while (node != null) { nextNode = node.Next; if (node.Value.IsAlive) {// The instance is still alive. if (node.Value.TargetId == targetId) { array[arrayCount++] = node.Value; } } else if (node.Value.ReferenceCount == 0) {// Garbage collected and reference count is 0. CloseChannel(node.Value); } node = nextNode; } } if (array.Length != arrayCount) { Array.Resize(ref array, arrayCount); } foreach (var x in array) { x.ReferenceCount++; } return(array); }
private static void CloseChannel(XChannel channel) {// lock (cs) required. Reference count must be 0. // list: Identification to XChannels. if (channel.Node != null) { var list = channel.Node.List; if (list != null) { list.Remove(channel.Node); } } channel.MarkForDeletion(); }
public static void Close(XChannel channel) { if (channel.Disposed == true) {// already closed. return; } while (true) { lock (cs) { if (channel.ReferenceCount == 0) {// reference countが0(Send / Receive処理をしていない状態)になったら、Close CloseChannel(channel); break; } } #if NETFX_CORE Task.Delay(50).Wait(); #else System.Threading.Thread.Sleep(50); #endif } }