/Microsoft.Build/Microsoft.Build/Microsoft/Build/BackEnd/NodeEndpointInProc.cs
C# | 299 lines | 276 code | 23 blank | 0 comment | 35 complexity | 2274f16b96d7360aedac2f4b5ec726cc MD5 | raw file
Possible License(s): Apache-2.0, LGPL-3.0
- namespace Microsoft.Build.BackEnd
- {
- using Microsoft.Build.Execution;
- using Microsoft.Build.Shared;
- using System;
- using System.Collections.Generic;
- using System.Runtime;
- using System.Runtime.InteropServices;
- using System.Threading;
-
- internal class NodeEndpointInProc : INodeEndpoint
- {
- private object asyncDataMonitor;
- private IBuildComponentHost componentHost;
- private static object locker = new object();
- private EndpointMode mode;
- private LinkStatusChangedDelegate OnLinkStatusChanged;
- private AutoResetEvent packetAvailable;
- private INodePacketFactory packetFactory;
- private Thread packetPump;
- private Queue<INodePacket> packetQueue;
- private bool peerConnected;
- private NodeEndpointInProc peerEndpoint;
- private Microsoft.Build.BackEnd.LinkStatus status;
- private AutoResetEvent terminatePacketPump;
-
- public event LinkStatusChangedDelegate OnLinkStatusChanged
- {
- add
- {
- LinkStatusChangedDelegate delegate3;
- LinkStatusChangedDelegate onLinkStatusChanged = this.OnLinkStatusChanged;
- do
- {
- delegate3 = onLinkStatusChanged;
- LinkStatusChangedDelegate delegate4 = (LinkStatusChangedDelegate) Delegate.Combine(delegate3, value);
- onLinkStatusChanged = Interlocked.CompareExchange<LinkStatusChangedDelegate>(ref this.OnLinkStatusChanged, delegate4, delegate3);
- }
- while (onLinkStatusChanged != delegate3);
- }
- remove
- {
- LinkStatusChangedDelegate delegate3;
- LinkStatusChangedDelegate onLinkStatusChanged = this.OnLinkStatusChanged;
- do
- {
- delegate3 = onLinkStatusChanged;
- LinkStatusChangedDelegate delegate4 = (LinkStatusChangedDelegate) Delegate.Remove(delegate3, value);
- onLinkStatusChanged = Interlocked.CompareExchange<LinkStatusChangedDelegate>(ref this.OnLinkStatusChanged, delegate4, delegate3);
- }
- while (onLinkStatusChanged != delegate3);
- }
- }
-
- private NodeEndpointInProc(EndpointMode commMode, IBuildComponentHost host)
- {
- ErrorUtilities.VerifyThrowArgumentNull(host, "host");
- this.status = Microsoft.Build.BackEnd.LinkStatus.Inactive;
- this.mode = commMode;
- this.componentHost = host;
- if (commMode == EndpointMode.Asynchronous)
- {
- this.asyncDataMonitor = new object();
- }
- }
-
- private void ChangeLinkStatus(Microsoft.Build.BackEnd.LinkStatus newStatus)
- {
- ErrorUtilities.VerifyThrow(this.status != newStatus, "Attempting to change status to existing status {0}.", this.status);
- this.status = newStatus;
- this.RaiseLinkStatusChanged(this.status);
- }
-
- public void Connect(INodePacketFactory factory)
- {
- ErrorUtilities.VerifyThrowInternalNull(factory, "factory");
- this.packetFactory = factory;
- if (this.mode == EndpointMode.Asynchronous)
- {
- this.InitializeAsyncPacketThread();
- }
- this.peerEndpoint.SetPeerNodeConnected();
- }
-
- internal static EndpointPair CreateInProcEndpoints(EndpointMode mode, IBuildComponentHost host)
- {
- NodeEndpointInProc node = new NodeEndpointInProc(mode, host);
- NodeEndpointInProc manager = new NodeEndpointInProc(mode, host);
- node.peerEndpoint = manager;
- manager.peerEndpoint = node;
- return new EndpointPair(node, manager);
- }
-
- public void Disconnect()
- {
- this.InternalDisconnect();
- this.peerEndpoint.SetPeerNodeDisconnected();
- }
-
- private void EnqueuePacket(INodePacket packet)
- {
- ErrorUtilities.VerifyThrowArgumentNull(packet, "packet");
- ErrorUtilities.VerifyThrow(this.mode == EndpointMode.Asynchronous, "EndPoint mode is synchronous, should be asynchronous");
- ErrorUtilities.VerifyThrow(null != this.packetQueue, "packetQueue is null");
- ErrorUtilities.VerifyThrow(null != this.packetAvailable, "packetAvailable is null");
- lock (this.packetQueue)
- {
- this.packetQueue.Enqueue(packet);
- this.packetAvailable.Set();
- }
- }
-
- private void InitializeAsyncPacketThread()
- {
- lock (this.asyncDataMonitor)
- {
- ErrorUtilities.VerifyThrow(null == this.packetPump, "packetPump != null");
- ErrorUtilities.VerifyThrow(null == this.packetAvailable, "packetAvailable != null");
- ErrorUtilities.VerifyThrow(null == this.terminatePacketPump, "terminatePacketPump != null");
- ErrorUtilities.VerifyThrow(null == this.packetQueue, "packetQueue != null");
- this.packetPump = new Thread(new ThreadStart(this.PacketPumpProc));
- this.packetPump.Name = "InProc Endpoint Packet Pump";
- this.packetAvailable = new AutoResetEvent(false);
- this.terminatePacketPump = new AutoResetEvent(false);
- this.packetQueue = new Queue<INodePacket>();
- this.packetPump.Start();
- }
- }
-
- private void InternalDisconnect()
- {
- ErrorUtilities.VerifyThrow(this.status == Microsoft.Build.BackEnd.LinkStatus.Active, "Endpoint is not connected. Current status {0}", this.status);
- this.ChangeLinkStatus(Microsoft.Build.BackEnd.LinkStatus.Inactive);
- if (this.mode == EndpointMode.Asynchronous)
- {
- this.TerminateAsyncPacketThread();
- }
- }
-
- public void Listen(INodePacketFactory factory)
- {
- ErrorUtilities.VerifyThrowInternalNull(factory, "factory");
- this.packetFactory = factory;
- if (this.mode == EndpointMode.Asynchronous)
- {
- this.InitializeAsyncPacketThread();
- }
- this.peerEndpoint.SetPeerNodeConnected();
- }
-
- private void PacketPumpProc()
- {
- try
- {
- int num;
- INodePacket packet;
- WaitHandle[] waitHandles = new WaitHandle[] { this.terminatePacketPump, this.packetAvailable };
- bool flag = false;
- Label_0021:
- num = WaitHandle.WaitAny(waitHandles);
- switch (num)
- {
- case 0:
- flag = true;
- goto Label_00F9;
-
- case 1:
- break;
-
- default:
- ErrorUtilities.ThrowInternalError("waitId {0} out of range.", new object[] { num });
- goto Label_00F9;
- }
- int count = 0;
- lock (this.packetQueue)
- {
- count = this.packetQueue.Count;
- goto Label_00D5;
- }
- Label_0075:
- packet = null;
- lock (this.packetQueue)
- {
- ErrorUtilities.VerifyThrow(this.packetQueue.Count > 0, "Packet Queue count is zero.");
- packet = this.packetQueue.Dequeue();
- }
- this.peerEndpoint.packetFactory.RoutePacket(0, packet);
- count--;
- Label_00D5:
- if (count > 0)
- {
- goto Label_0075;
- }
- Label_00F9:
- if (!flag)
- {
- goto Label_0021;
- }
- }
- catch (Exception exception)
- {
- ExceptionHandling.DumpExceptionToFile(exception);
- throw;
- }
- }
-
- private void RaiseLinkStatusChanged(Microsoft.Build.BackEnd.LinkStatus newStatus)
- {
- if (this.OnLinkStatusChanged != null)
- {
- LinkStatusChangedDelegate delegate2 = (LinkStatusChangedDelegate) this.OnLinkStatusChanged.Clone();
- delegate2(this, newStatus);
- }
- }
-
- public void SendData(INodePacket packet)
- {
- ErrorUtilities.VerifyThrow(this.status == Microsoft.Build.BackEnd.LinkStatus.Active, "Cannot send when link status is not active. Current status {0}", this.status);
- if (this.mode == EndpointMode.Synchronous)
- {
- this.peerEndpoint.packetFactory.RoutePacket(0, packet);
- }
- else
- {
- this.EnqueuePacket(packet);
- }
- }
-
- private void SetPeerNodeConnected()
- {
- lock (locker)
- {
- this.peerConnected = true;
- if (this.peerEndpoint.peerConnected)
- {
- this.ChangeLinkStatus(Microsoft.Build.BackEnd.LinkStatus.Active);
- this.peerEndpoint.ChangeLinkStatus(Microsoft.Build.BackEnd.LinkStatus.Active);
- }
- }
- }
-
- private void SetPeerNodeDisconnected()
- {
- this.peerConnected = false;
- this.InternalDisconnect();
- }
-
- private void TerminateAsyncPacketThread()
- {
- lock (this.asyncDataMonitor)
- {
- ErrorUtilities.VerifyThrow(null != this.packetPump, "packetPump == null");
- ErrorUtilities.VerifyThrow(null != this.packetAvailable, "packetAvailable == null");
- ErrorUtilities.VerifyThrow(null != this.terminatePacketPump, "terminatePacketPump == null");
- ErrorUtilities.VerifyThrow(null != this.packetQueue, "packetQueue == null");
- this.terminatePacketPump.Set();
- if (!this.packetPump.Join(new TimeSpan(0, 0, BuildParameters.EndpointShutdownTimeout)))
- {
- this.packetPump.Abort();
- }
- this.packetPump = null;
- this.packetAvailable.Close();
- this.packetAvailable = null;
- this.terminatePacketPump.Close();
- this.terminatePacketPump = null;
- this.packetQueue = null;
- }
- }
-
- public Microsoft.Build.BackEnd.LinkStatus LinkStatus
- {
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- get
- {
- return this.status;
- }
- }
-
- internal enum EndpointMode
- {
- Synchronous,
- Asynchronous
- }
-
- [StructLayout(LayoutKind.Sequential)]
- internal struct EndpointPair
- {
- internal readonly NodeEndpointInProc NodeEndpoint;
- internal readonly NodeEndpointInProc ManagerEndpoint;
- [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
- internal EndpointPair(NodeEndpointInProc node, NodeEndpointInProc manager)
- {
- this.NodeEndpoint = node;
- this.ManagerEndpoint = manager;
- }
- }
- }
- }
-