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

/src/Microsoft.AspNet.SignalR.Hosting.Memory/AsyncResult.cs

https://github.com/h3rd4/SignalR
C# | 162 lines | 112 code | 25 blank | 25 comment | 15 complexity | e55e25538e99f12ff258723e04adc543 MD5 | raw file
Possible License(s): Apache-2.0
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
  2. using System;
  3. using System.Diagnostics.CodeAnalysis;
  4. using System.Threading;
  5. namespace Microsoft.AspNet.SignalR.Hosting.Memory
  6. {
  7. // From http://msdn.microsoft.com/en-us/magazine/cc163467.aspx
  8. internal class AsyncResult : IAsyncResult
  9. {
  10. // Fields set at construction which never change while
  11. // operation is pending
  12. readonly AsyncCallback m_AsyncCallback;
  13. readonly Object m_AsyncState;
  14. // Fields set at construction which do change after
  15. // operation completes
  16. const Int32 c_StatePending = 0;
  17. const Int32 c_StateCompletedSynchronously = 1;
  18. const Int32 c_StateCompletedAsynchronously = 2;
  19. Int32 m_CompletedState = c_StatePending;
  20. // Field that may or may not get set depending on usage
  21. ManualResetEvent m_AsyncWaitHandle;
  22. // Fields set when operation completes
  23. Exception m_exception;
  24. public AsyncResult(AsyncCallback asyncCallback, Object state)
  25. {
  26. m_AsyncCallback = asyncCallback;
  27. m_AsyncState = state;
  28. }
  29. public void SetAsCompleted(
  30. Exception exception, Boolean completedSynchronously)
  31. {
  32. // Passing null for exception means no error occurred.
  33. // This is the common case
  34. m_exception = exception;
  35. // The m_CompletedState field MUST be set prior calling the callback
  36. Int32 prevState = Interlocked.Exchange(ref m_CompletedState,
  37. completedSynchronously
  38. ? c_StateCompletedSynchronously
  39. : c_StateCompletedAsynchronously);
  40. if (prevState != c_StatePending)
  41. throw new InvalidOperationException(
  42. "You can set a result only once");
  43. // If the event exists, set it
  44. if (m_AsyncWaitHandle != null) m_AsyncWaitHandle.Set();
  45. // If a callback method was set, call it
  46. if (m_AsyncCallback != null) m_AsyncCallback(this);
  47. }
  48. public void EndInvoke()
  49. {
  50. // This method assumes that only 1 thread calls EndInvoke
  51. // for this object
  52. if (!IsCompleted)
  53. {
  54. // If the operation isn't done, wait for it
  55. AsyncWaitHandle.WaitOne();
  56. AsyncWaitHandle.Close();
  57. m_AsyncWaitHandle = null; // Allow early GC
  58. }
  59. // Operation is done: if an exception occured, throw it
  60. if (m_exception != null) throw m_exception;
  61. }
  62. #region Implementation of IAsyncResult
  63. public Object AsyncState
  64. {
  65. get { return m_AsyncState; }
  66. }
  67. public Boolean CompletedSynchronously
  68. {
  69. get
  70. {
  71. return Thread.VolatileRead(ref m_CompletedState) ==
  72. c_StateCompletedSynchronously;
  73. }
  74. }
  75. [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "It's disposed elsewhere")]
  76. public WaitHandle AsyncWaitHandle
  77. {
  78. get
  79. {
  80. if (m_AsyncWaitHandle == null)
  81. {
  82. Boolean done = IsCompleted;
  83. ManualResetEvent mre = new ManualResetEvent(done);
  84. if (Interlocked.CompareExchange(ref m_AsyncWaitHandle,
  85. mre, null) != null)
  86. {
  87. // Another thread created this object's event; dispose
  88. // the event we just created
  89. mre.Close();
  90. }
  91. else
  92. {
  93. if (!done && IsCompleted)
  94. {
  95. // If the operation wasn't done when we created
  96. // the event but now it is done, set the event
  97. m_AsyncWaitHandle.Set();
  98. }
  99. }
  100. }
  101. return m_AsyncWaitHandle;
  102. }
  103. }
  104. public Boolean IsCompleted
  105. {
  106. get
  107. {
  108. return Thread.VolatileRead(ref m_CompletedState) !=
  109. c_StatePending;
  110. }
  111. }
  112. #endregion
  113. }
  114. internal class AsyncResult<TResult> : AsyncResult
  115. {
  116. // Field set when operation completes
  117. TResult m_result = default(TResult);
  118. public AsyncResult(AsyncCallback asyncCallback, Object state) :
  119. base(asyncCallback, state)
  120. {
  121. }
  122. public void SetAsCompleted(TResult result,
  123. Boolean completedSynchronously)
  124. {
  125. // Save the asynchronous operation's result
  126. m_result = result;
  127. // Tell the base class that the operation completed
  128. // sucessfully (no exception)
  129. base.SetAsCompleted(null, completedSynchronously);
  130. }
  131. public new TResult EndInvoke()
  132. {
  133. base.EndInvoke(); // Wait until operation has completed
  134. return m_result; // Return the result (if above didn't throw)
  135. }
  136. }
  137. }