Barrier.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #if NET_4_0
  2. //
  3. // Barrier.cs
  4. //
  5. // Author:
  6. // Jérémie "Garuma" Laval <[email protected]>
  7. //
  8. // Copyright (c) 2009 Jérémie "Garuma" Laval
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining a copy
  11. // of this software and associated documentation files (the "Software"), to deal
  12. // in the Software without restriction, including without limitation the rights
  13. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  14. // copies of the Software, and to permit persons to whom the Software is
  15. // furnished to do so, subject to the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be included in
  18. // all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  23. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  25. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  26. // THE SOFTWARE.
  27. using System;
  28. namespace System.Threading
  29. {
  30. public class Barrier
  31. {
  32. readonly Action<Barrier> postPhaseAction;
  33. int participants;
  34. CountdownEvent cntd;
  35. AtomicBoolean cleaned = new AtomicBoolean ();
  36. int phase;
  37. public Barrier (int participants) : this (participants, null)
  38. {
  39. }
  40. public Barrier (int participants, Action<Barrier> postPhaseAction)
  41. {
  42. this.participants = participants;
  43. this.postPhaseAction = postPhaseAction;
  44. InitCountdownEvent ();
  45. }
  46. void InitCountdownEvent ()
  47. {
  48. cleaned = new AtomicBoolean ();
  49. cntd = new CountdownEvent (participants);
  50. }
  51. public int AddParticipant ()
  52. {
  53. return AddParticipants (1);
  54. }
  55. public int AddParticipants (int participantCount)
  56. {
  57. // Basically, we try to add ourselves and return
  58. // the phase. If the call return false, we repeatdly try
  59. // to add ourselves for the next phase
  60. do {
  61. if (cntd.TryAddCount (participantCount)) {
  62. Interlocked.Add (ref participants, participantCount);
  63. return phase;
  64. }
  65. } while (true);
  66. }
  67. public void RemoveParticipant ()
  68. {
  69. RemoveParticipants (1);
  70. }
  71. public void RemoveParticipants (int participantCount)
  72. {
  73. cntd.Signal (participantCount);
  74. Interlocked.Add (ref participants, -participantCount);
  75. }
  76. public void SignalAndWait ()
  77. {
  78. SignalAndWait ((c) => { c.Wait (); return true; });
  79. }
  80. public bool SignalAndWait (int millisecondTimeout)
  81. {
  82. return SignalAndWait ((c) => c.Wait (millisecondTimeout));
  83. }
  84. public bool SignalAndWait (TimeSpan ts)
  85. {
  86. return SignalAndWait ((c) => c.Wait (ts));
  87. }
  88. public bool SignalAndWait (int millisecondTimeout, CancellationToken token)
  89. {
  90. return SignalAndWait ((c) => c.Wait (millisecondTimeout, token));
  91. }
  92. public bool SignalAndWait (TimeSpan ts, CancellationToken token)
  93. {
  94. return SignalAndWait ((c) => c.Wait (ts, token));
  95. }
  96. bool SignalAndWait (Func<CountdownEvent, bool> associate)
  97. {
  98. bool result;
  99. AtomicBoolean cl = cleaned;
  100. CountdownEvent temp = cntd;
  101. if (!temp.Signal ()) {
  102. result = Wait (associate, temp, cl);
  103. } else {
  104. result = true;
  105. PostPhaseAction (cl);
  106. phase++;
  107. }
  108. return result;
  109. }
  110. bool Wait (Func<CountdownEvent, bool> associate, CountdownEvent temp, AtomicBoolean cl)
  111. {
  112. if (!associate (temp))
  113. return false;
  114. SpinWait sw = new SpinWait ();
  115. while (!cl.Value) {
  116. //Console.WriteLine (cleaned);
  117. sw.SpinOnce ();
  118. }
  119. return true;
  120. }
  121. void PostPhaseAction (AtomicBoolean cl)
  122. {
  123. postPhaseAction (this);
  124. InitCountdownEvent ();
  125. cl.Value = true;
  126. }
  127. public int CurrentPhaseNumber {
  128. get {
  129. return phase;
  130. }
  131. }
  132. public int ParticipantCount {
  133. get {
  134. return participants;
  135. }
  136. }
  137. }
  138. }
  139. #endif