Monitor.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. //
  2. // System.Threading.Monitor.cs
  3. //
  4. // Author:
  5. // Dick Porter ([email protected])
  6. //
  7. // (C) Ximian, Inc. http://www.ximian.com
  8. //
  9. using System.Runtime.CompilerServices;
  10. namespace System.Threading
  11. {
  12. public sealed class Monitor
  13. {
  14. // Grabs the mutex on object 'obj', with a maximum
  15. // wait time 'ms' but doesn't block - if it can't get
  16. // the lock it returns false, true if it can
  17. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  18. private extern static bool Monitor_try_enter(object obj, int ms);
  19. public static void Enter(object obj) {
  20. if(obj==null) {
  21. throw new ArgumentNullException("Object is null");
  22. }
  23. //if(obj.GetType().IsValueType==true) {
  24. // throw new ArgumentException("Value type");
  25. //}
  26. Monitor_try_enter(obj, Timeout.Infinite);
  27. }
  28. // Releases the mutex on object 'obj'
  29. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  30. private extern static void Monitor_exit(object obj);
  31. // Checks whether the current thread currently owns
  32. // the lock on object 'obj'
  33. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  34. private extern static bool Monitor_test_owner(object obj);
  35. public static void Exit(object obj) {
  36. if(obj==null) {
  37. throw new ArgumentNullException("Object is null");
  38. }
  39. //if(obj.GetType().IsValueType==true) {
  40. // throw new ArgumentException("Value type");
  41. //}
  42. if(Monitor_test_owner(obj)==false) {
  43. throw new SynchronizationLockException("The current thread does not own the lock");
  44. }
  45. Monitor_exit(obj);
  46. }
  47. // Signals one of potentially many objects waiting on
  48. // object 'obj'
  49. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  50. private extern static void Monitor_pulse(object obj);
  51. // Checks whether object 'obj' is currently synchronised
  52. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  53. private extern static bool Monitor_test_synchronised(object obj);
  54. public static void Pulse(object obj) {
  55. if(obj==null) {
  56. throw new ArgumentNullException("Object is null");
  57. }
  58. if(Monitor_test_synchronised(obj)==false) {
  59. throw new SynchronizationLockException("Object is not synchronised");
  60. }
  61. Monitor_pulse(obj);
  62. }
  63. // Signals all of potentially many objects waiting on
  64. // object 'obj'
  65. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  66. private extern static void Monitor_pulse_all(object obj);
  67. public static void PulseAll(object obj) {
  68. if(obj==null) {
  69. throw new ArgumentNullException("Object is null");
  70. }
  71. if(Monitor_test_synchronised(obj)==false) {
  72. throw new SynchronizationLockException("Object is not synchronised");
  73. }
  74. Monitor_pulse_all(obj);
  75. }
  76. public static bool TryEnter(object obj) {
  77. if(obj==null) {
  78. throw new ArgumentNullException("Object is null");
  79. }
  80. //if(obj.GetType().IsValueType==true) {
  81. // throw new ArgumentException("Value type");
  82. //}
  83. return(Monitor_try_enter(obj, 0));
  84. }
  85. public static bool TryEnter(object obj, int millisecondsTimeout) {
  86. if(obj==null) {
  87. throw new ArgumentNullException("Object is null");
  88. }
  89. //if(obj.GetType().IsValueType==true) {
  90. // throw new ArgumentException("Value type");
  91. //}
  92. // LAMESPEC: should throw an exception when ms<0, but
  93. // Timeout.Infinite is -1
  94. if(millisecondsTimeout == Timeout.Infinite) {
  95. Enter(obj);
  96. return(true);
  97. }
  98. if(millisecondsTimeout<0) {
  99. throw new ArgumentException("millisecondsTimeout negative");
  100. }
  101. return(Monitor_try_enter(obj, millisecondsTimeout));
  102. }
  103. public static bool TryEnter(object obj, TimeSpan timeout) {
  104. if(obj==null) {
  105. throw new ArgumentNullException("Object is null");
  106. }
  107. //if(obj.GetType().IsValueType==true) {
  108. // throw new ArgumentException("Value type");
  109. //}
  110. // LAMESPEC: should throw an exception when ms<0, but
  111. // Timeout.Infinite is -1
  112. if(timeout.Milliseconds == Timeout.Infinite) {
  113. Enter(obj);
  114. return(true);
  115. }
  116. if(timeout.Milliseconds < 0 ||
  117. timeout.Milliseconds > Int32.MaxValue) {
  118. throw new ArgumentOutOfRangeException("timeout out of range");
  119. }
  120. return(Monitor_try_enter(obj, timeout.Milliseconds));
  121. }
  122. // Waits for a signal on object 'obj' with maximum
  123. // wait time 'ms'. Returns true if the object was
  124. // signalled, false if it timed out
  125. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  126. private extern static bool Monitor_wait(object obj, int ms);
  127. public static bool Wait(object obj) {
  128. if(obj==null) {
  129. throw new ArgumentNullException("Object is null");
  130. }
  131. if(Monitor_test_synchronised(obj)==false) {
  132. throw new SynchronizationLockException("Object is not synchronised");
  133. }
  134. return(Monitor_wait(obj, 0));
  135. }
  136. public static bool Wait(object obj, int millisecondsTimeout) {
  137. if(obj==null) {
  138. throw new ArgumentNullException("Object is null");
  139. }
  140. if(Monitor_test_synchronised(obj)==false) {
  141. throw new SynchronizationLockException("Object is not synchronised");
  142. }
  143. // LAMESPEC: no mention of timeout sanity checking
  144. return(Monitor_wait(obj, millisecondsTimeout));
  145. }
  146. public static bool Wait(object obj, TimeSpan timeout) {
  147. if(obj==null) {
  148. throw new ArgumentNullException("Object is null");
  149. }
  150. // LAMESPEC: says to throw ArgumentException too
  151. if(timeout.Milliseconds < 0 || timeout.Milliseconds > Int32.MaxValue) {
  152. throw new ArgumentOutOfRangeException("timeout out of range");
  153. }
  154. if(Monitor_test_synchronised(obj)==false) {
  155. throw new SynchronizationLockException("Object is not synchronised");
  156. }
  157. return(Monitor_wait(obj, timeout.Milliseconds));
  158. }
  159. [MonoTODO]
  160. public static bool Wait(object obj, int millisecondsTimeout, bool exitContext) {
  161. if(obj==null) {
  162. throw new ArgumentNullException("Object is null");
  163. }
  164. // FIXME when I understand what a
  165. // "synchronisation domain" is and does
  166. return(false);
  167. }
  168. [MonoTODO]
  169. public static bool Wait(object obj, TimeSpan timeout, bool exitContext) {
  170. if(obj==null) {
  171. throw new ArgumentNullException("Object is null");
  172. }
  173. // LAMESPEC: says to throw ArgumentException too
  174. if(timeout.Milliseconds < 0 || timeout.Milliseconds > Int32.MaxValue) {
  175. throw new ArgumentOutOfRangeException("timeout out of range");
  176. }
  177. // FIXME when I understand what a
  178. // "synchronisation domain" is and does
  179. return(false);
  180. }
  181. }
  182. }