PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  1. namespace Microsoft.Build.BackEnd
  2. {
  3. using Microsoft.Build.Execution;
  4. using Microsoft.Build.Shared;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Runtime;
  8. using System.Runtime.InteropServices;
  9. using System.Threading;
  10. internal class NodeEndpointInProc : INodeEndpoint
  11. {
  12. private object asyncDataMonitor;
  13. private IBuildComponentHost componentHost;
  14. private static object locker = new object();
  15. private EndpointMode mode;
  16. private LinkStatusChangedDelegate OnLinkStatusChanged;
  17. private AutoResetEvent packetAvailable;
  18. private INodePacketFactory packetFactory;
  19. private Thread packetPump;
  20. private Queue<INodePacket> packetQueue;
  21. private bool peerConnected;
  22. private NodeEndpointInProc peerEndpoint;
  23. private Microsoft.Build.BackEnd.LinkStatus status;
  24. private AutoResetEvent terminatePacketPump;
  25. public event LinkStatusChangedDelegate OnLinkStatusChanged
  26. {
  27. add
  28. {
  29. LinkStatusChangedDelegate delegate3;
  30. LinkStatusChangedDelegate onLinkStatusChanged = this.OnLinkStatusChanged;
  31. do
  32. {
  33. delegate3 = onLinkStatusChanged;
  34. LinkStatusChangedDelegate delegate4 = (LinkStatusChangedDelegate) Delegate.Combine(delegate3, value);
  35. onLinkStatusChanged = Interlocked.CompareExchange<LinkStatusChangedDelegate>(ref this.OnLinkStatusChanged, delegate4, delegate3);
  36. }
  37. while (onLinkStatusChanged != delegate3);
  38. }
  39. remove
  40. {
  41. LinkStatusChangedDelegate delegate3;
  42. LinkStatusChangedDelegate onLinkStatusChanged = this.OnLinkStatusChanged;
  43. do
  44. {
  45. delegate3 = onLinkStatusChanged;
  46. LinkStatusChangedDelegate delegate4 = (LinkStatusChangedDelegate) Delegate.Remove(delegate3, value);
  47. onLinkStatusChanged = Interlocked.CompareExchange<LinkStatusChangedDelegate>(ref this.OnLinkStatusChanged, delegate4, delegate3);
  48. }
  49. while (onLinkStatusChanged != delegate3);
  50. }
  51. }
  52. private NodeEndpointInProc(EndpointMode commMode, IBuildComponentHost host)
  53. {
  54. ErrorUtilities.VerifyThrowArgumentNull(host, "host");
  55. this.status = Microsoft.Build.BackEnd.LinkStatus.Inactive;
  56. this.mode = commMode;
  57. this.componentHost = host;
  58. if (commMode == EndpointMode.Asynchronous)
  59. {
  60. this.asyncDataMonitor = new object();
  61. }
  62. }
  63. private void ChangeLinkStatus(Microsoft.Build.BackEnd.LinkStatus newStatus)
  64. {
  65. ErrorUtilities.VerifyThrow(this.status != newStatus, "Attempting to change status to existing status {0}.", this.status);
  66. this.status = newStatus;
  67. this.RaiseLinkStatusChanged(this.status);
  68. }
  69. public void Connect(INodePacketFactory factory)
  70. {
  71. ErrorUtilities.VerifyThrowInternalNull(factory, "factory");
  72. this.packetFactory = factory;
  73. if (this.mode == EndpointMode.Asynchronous)
  74. {
  75. this.InitializeAsyncPacketThread();
  76. }
  77. this.peerEndpoint.SetPeerNodeConnected();
  78. }
  79. internal static EndpointPair CreateInProcEndpoints(EndpointMode mode, IBuildComponentHost host)
  80. {
  81. NodeEndpointInProc node = new NodeEndpointInProc(mode, host);
  82. NodeEndpointInProc manager = new NodeEndpointInProc(mode, host);
  83. node.peerEndpoint = manager;
  84. manager.peerEndpoint = node;
  85. return new EndpointPair(node, manager);
  86. }
  87. public void Disconnect()
  88. {
  89. this.InternalDisconnect();
  90. this.peerEndpoint.SetPeerNodeDisconnected();
  91. }
  92. private void EnqueuePacket(INodePacket packet)
  93. {
  94. ErrorUtilities.VerifyThrowArgumentNull(packet, "packet");
  95. ErrorUtilities.VerifyThrow(this.mode == EndpointMode.Asynchronous, "EndPoint mode is synchronous, should be asynchronous");
  96. ErrorUtilities.VerifyThrow(null != this.packetQueue, "packetQueue is null");
  97. ErrorUtilities.VerifyThrow(null != this.packetAvailable, "packetAvailable is null");
  98. lock (this.packetQueue)
  99. {
  100. this.packetQueue.Enqueue(packet);
  101. this.packetAvailable.Set();
  102. }
  103. }
  104. private void InitializeAsyncPacketThread()
  105. {
  106. lock (this.asyncDataMonitor)
  107. {
  108. ErrorUtilities.VerifyThrow(null == this.packetPump, "packetPump != null");
  109. ErrorUtilities.VerifyThrow(null == this.packetAvailable, "packetAvailable != null");
  110. ErrorUtilities.VerifyThrow(null == this.terminatePacketPump, "terminatePacketPump != null");
  111. ErrorUtilities.VerifyThrow(null == this.packetQueue, "packetQueue != null");
  112. this.packetPump = new Thread(new ThreadStart(this.PacketPumpProc));
  113. this.packetPump.Name = "InProc Endpoint Packet Pump";
  114. this.packetAvailable = new AutoResetEvent(false);
  115. this.terminatePacketPump = new AutoResetEvent(false);
  116. this.packetQueue = new Queue<INodePacket>();
  117. this.packetPump.Start();
  118. }
  119. }
  120. private void InternalDisconnect()
  121. {
  122. ErrorUtilities.VerifyThrow(this.status == Microsoft.Build.BackEnd.LinkStatus.Active, "Endpoint is not connected. Current status {0}", this.status);
  123. this.ChangeLinkStatus(Microsoft.Build.BackEnd.LinkStatus.Inactive);
  124. if (this.mode == EndpointMode.Asynchronous)
  125. {
  126. this.TerminateAsyncPacketThread();
  127. }
  128. }
  129. public void Listen(INodePacketFactory factory)
  130. {
  131. ErrorUtilities.VerifyThrowInternalNull(factory, "factory");
  132. this.packetFactory = factory;
  133. if (this.mode == EndpointMode.Asynchronous)
  134. {
  135. this.InitializeAsyncPacketThread();
  136. }
  137. this.peerEndpoint.SetPeerNodeConnected();
  138. }
  139. private void PacketPumpProc()
  140. {
  141. try
  142. {
  143. int num;
  144. INodePacket packet;
  145. WaitHandle[] waitHandles = new WaitHandle[] { this.terminatePacketPump, this.packetAvailable };
  146. bool flag = false;
  147. Label_0021:
  148. num = WaitHandle.WaitAny(waitHandles);
  149. switch (num)
  150. {
  151. case 0:
  152. flag = true;
  153. goto Label_00F9;
  154. case 1:
  155. break;
  156. default:
  157. ErrorUtilities.ThrowInternalError("waitId {0} out of range.", new object[] { num });
  158. goto Label_00F9;
  159. }
  160. int count = 0;
  161. lock (this.packetQueue)
  162. {
  163. count = this.packetQueue.Count;
  164. goto Label_00D5;
  165. }
  166. Label_0075:
  167. packet = null;
  168. lock (this.packetQueue)
  169. {
  170. ErrorUtilities.VerifyThrow(this.packetQueue.Count > 0, "Packet Queue count is zero.");
  171. packet = this.packetQueue.Dequeue();
  172. }
  173. this.peerEndpoint.packetFactory.RoutePacket(0, packet);
  174. count--;
  175. Label_00D5:
  176. if (count > 0)
  177. {
  178. goto Label_0075;
  179. }
  180. Label_00F9:
  181. if (!flag)
  182. {
  183. goto Label_0021;
  184. }
  185. }
  186. catch (Exception exception)
  187. {
  188. ExceptionHandling.DumpExceptionToFile(exception);
  189. throw;
  190. }
  191. }
  192. private void RaiseLinkStatusChanged(Microsoft.Build.BackEnd.LinkStatus newStatus)
  193. {
  194. if (this.OnLinkStatusChanged != null)
  195. {
  196. LinkStatusChangedDelegate delegate2 = (LinkStatusChangedDelegate) this.OnLinkStatusChanged.Clone();
  197. delegate2(this, newStatus);
  198. }
  199. }
  200. public void SendData(INodePacket packet)
  201. {
  202. ErrorUtilities.VerifyThrow(this.status == Microsoft.Build.BackEnd.LinkStatus.Active, "Cannot send when link status is not active. Current status {0}", this.status);
  203. if (this.mode == EndpointMode.Synchronous)
  204. {
  205. this.peerEndpoint.packetFactory.RoutePacket(0, packet);
  206. }
  207. else
  208. {
  209. this.EnqueuePacket(packet);
  210. }
  211. }
  212. private void SetPeerNodeConnected()
  213. {
  214. lock (locker)
  215. {
  216. this.peerConnected = true;
  217. if (this.peerEndpoint.peerConnected)
  218. {
  219. this.ChangeLinkStatus(Microsoft.Build.BackEnd.LinkStatus.Active);
  220. this.peerEndpoint.ChangeLinkStatus(Microsoft.Build.BackEnd.LinkStatus.Active);
  221. }
  222. }
  223. }
  224. private void SetPeerNodeDisconnected()
  225. {
  226. this.peerConnected = false;
  227. this.InternalDisconnect();
  228. }
  229. private void TerminateAsyncPacketThread()
  230. {
  231. lock (this.asyncDataMonitor)
  232. {
  233. ErrorUtilities.VerifyThrow(null != this.packetPump, "packetPump == null");
  234. ErrorUtilities.VerifyThrow(null != this.packetAvailable, "packetAvailable == null");
  235. ErrorUtilities.VerifyThrow(null != this.terminatePacketPump, "terminatePacketPump == null");
  236. ErrorUtilities.VerifyThrow(null != this.packetQueue, "packetQueue == null");
  237. this.terminatePacketPump.Set();
  238. if (!this.packetPump.Join(new TimeSpan(0, 0, BuildParameters.EndpointShutdownTimeout)))
  239. {
  240. this.packetPump.Abort();
  241. }
  242. this.packetPump = null;
  243. this.packetAvailable.Close();
  244. this.packetAvailable = null;
  245. this.terminatePacketPump.Close();
  246. this.terminatePacketPump = null;
  247. this.packetQueue = null;
  248. }
  249. }
  250. public Microsoft.Build.BackEnd.LinkStatus LinkStatus
  251. {
  252. [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  253. get
  254. {
  255. return this.status;
  256. }
  257. }
  258. internal enum EndpointMode
  259. {
  260. Synchronous,
  261. Asynchronous
  262. }
  263. [StructLayout(LayoutKind.Sequential)]
  264. internal struct EndpointPair
  265. {
  266. internal readonly NodeEndpointInProc NodeEndpoint;
  267. internal readonly NodeEndpointInProc ManagerEndpoint;
  268. [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
  269. internal EndpointPair(NodeEndpointInProc node, NodeEndpointInProc manager)
  270. {
  271. this.NodeEndpoint = node;
  272. this.ManagerEndpoint = manager;
  273. }
  274. }
  275. }
  276. }