SimpleAsyncResult.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. //
  2. // SimpleAsyncResult.cs
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. // Martin Baulig ([email protected])
  7. //
  8. // (C) 2003 Ximian, Inc (http://www.ximian.com)
  9. // Copyright (c) 2014 Xamarin Inc. (http://www.xamarin.com)
  10. //
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System.IO;
  32. using System.Threading;
  33. namespace System.Net
  34. {
  35. delegate void SimpleAsyncCallback (SimpleAsyncResult result);
  36. class SimpleAsyncResult : IAsyncResult
  37. {
  38. ManualResetEvent handle;
  39. bool synch;
  40. bool isCompleted;
  41. readonly SimpleAsyncCallback cb;
  42. object state;
  43. bool callbackDone;
  44. Exception exc;
  45. object locker = new object ();
  46. SimpleAsyncResult (SimpleAsyncCallback cb)
  47. {
  48. this.cb = cb;
  49. }
  50. protected SimpleAsyncResult (AsyncCallback cb, object state)
  51. {
  52. this.state = state;
  53. this.cb = result => {
  54. if (cb != null)
  55. cb (this);
  56. };
  57. }
  58. public static void Run (Func<SimpleAsyncResult, bool> func, SimpleAsyncCallback callback)
  59. {
  60. var result = new SimpleAsyncResult (callback);
  61. try {
  62. if (!func (result))
  63. result.SetCompleted (true);
  64. } catch (Exception ex) {
  65. result.SetCompleted (true, ex);
  66. }
  67. }
  68. public static void RunWithLock (object locker, Func<SimpleAsyncResult, bool> func, SimpleAsyncCallback callback)
  69. {
  70. Run (inner => {
  71. bool running = func (inner);
  72. if (running)
  73. Monitor.Exit (locker);
  74. return running;
  75. }, inner => {
  76. if (inner.GotException) {
  77. if (inner.synch)
  78. Monitor.Exit (locker);
  79. callback (inner);
  80. return;
  81. }
  82. try {
  83. if (!inner.synch)
  84. Monitor.Enter (locker);
  85. callback (inner);
  86. } finally {
  87. Monitor.Exit (locker);
  88. }
  89. });
  90. }
  91. protected void Reset_internal ()
  92. {
  93. callbackDone = false;
  94. exc = null;
  95. lock (locker) {
  96. isCompleted = false;
  97. if (handle != null)
  98. handle.Reset ();
  99. }
  100. }
  101. internal void SetCompleted (bool synch, Exception e)
  102. {
  103. SetCompleted_internal (synch, e);
  104. DoCallback_private ();
  105. }
  106. internal void SetCompleted (bool synch)
  107. {
  108. SetCompleted_internal (synch);
  109. DoCallback_private ();
  110. }
  111. void SetCompleted_internal (bool synch, Exception e)
  112. {
  113. this.synch = synch;
  114. exc = e;
  115. lock (locker) {
  116. isCompleted = true;
  117. if (handle != null)
  118. handle.Set ();
  119. }
  120. }
  121. protected void SetCompleted_internal (bool synch)
  122. {
  123. SetCompleted_internal (synch, null);
  124. }
  125. void DoCallback_private ()
  126. {
  127. if (callbackDone)
  128. return;
  129. callbackDone = true;
  130. if (cb == null)
  131. return;
  132. cb (this);
  133. }
  134. protected void DoCallback_internal ()
  135. {
  136. if (!callbackDone && cb != null) {
  137. callbackDone = true;
  138. cb (this);
  139. }
  140. }
  141. internal void WaitUntilComplete ()
  142. {
  143. if (IsCompleted)
  144. return;
  145. AsyncWaitHandle.WaitOne ();
  146. }
  147. internal bool WaitUntilComplete (int timeout, bool exitContext)
  148. {
  149. if (IsCompleted)
  150. return true;
  151. return AsyncWaitHandle.WaitOne (timeout, exitContext);
  152. }
  153. public object AsyncState {
  154. get { return state; }
  155. }
  156. public WaitHandle AsyncWaitHandle {
  157. get {
  158. lock (locker) {
  159. if (handle == null)
  160. handle = new ManualResetEvent (isCompleted);
  161. }
  162. return handle;
  163. }
  164. }
  165. bool? user_read_synch;
  166. public bool CompletedSynchronously {
  167. get {
  168. //
  169. // CompletedSynchronously (for System.Net networking stack) means "was the operation completed before the first time
  170. // that somebody asked if it was completed synchronously"? They do this because some of their asynchronous operations
  171. // (particularly those in the Socket class) will avoid the cost of capturing and transferring the ExecutionContext
  172. // to the callback thread by checking CompletedSynchronously, and calling the callback from within BeginXxx instead of
  173. // on the completion port thread if the native winsock call completes quickly.
  174. //
  175. // TODO: racy
  176. if (user_read_synch != null)
  177. return user_read_synch.Value;
  178. user_read_synch = synch;
  179. return user_read_synch.Value;
  180. }
  181. }
  182. internal bool CompletedSynchronouslyPeek {
  183. get {
  184. return synch;
  185. }
  186. }
  187. public bool IsCompleted {
  188. get {
  189. lock (locker) {
  190. return isCompleted;
  191. }
  192. }
  193. }
  194. internal bool GotException {
  195. get { return (exc != null); }
  196. }
  197. internal Exception Exception {
  198. get { return exc; }
  199. }
  200. }
  201. }