public void BasicUsageTest () { int[] array = null; var evt = new ManualResetEventSlim (false); var buffer = new BatchBlock<int> (10); var block = new ActionBlock<int[]> (i => { array = i; evt.Set (); }); buffer.LinkTo<int[]> (block); for (int i = 0; i < 9; i++) Assert.IsTrue (buffer.Post (i)); Assert.IsFalse (evt.Wait (100)); Assert.IsNull (array); Assert.IsTrue (buffer.Post (42)); Assert.IsTrue (evt.Wait (1000)); Assert.IsNotNull (array); CollectionAssert.AreEqual (new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 42 }, array); }
public void TestTimerStartAutoReset() { using (var timer = new TestTimer(1)) { var mres = new ManualResetEventSlim(); int count = 0; int target = 1; timer.AutoReset = false; timer.Elapsed += (sender, e) => { if (Interlocked.Increment(ref count) == target) { mres.Set(); } }; timer.Start(); mres.Wait(); Assert.False(timer.Enabled, "Auto-reset timer should not be enabled after elapsed"); Assert.Equal(1, count); count = 0; target = 10; mres.Reset(); timer.AutoReset = true; mres.Wait(); timer.Stop(); Assert.InRange(count, target, int.MaxValue); } }
public void BasicUsageTest () { Tuple<IList<int>, IList<int>, IList<string>> result = null; var evt = new ManualResetEventSlim (false); var actionBlock = new ActionBlock<Tuple<IList<int>, IList<int>, IList<string>>> (r => { result = r; evt.Set (); }); var block = new BatchedJoinBlock<int, int, string> (3); block.LinkTo (actionBlock); // all targets once Assert.IsTrue (block.Target1.Post (1)); Assert.IsTrue (block.Target2.Post (2)); Assert.IsFalse (evt.Wait (100)); Assert.IsNull (result); Assert.IsTrue (block.Target3.Post ("foo")); Assert.IsTrue (evt.Wait (1000)); Assert.IsNotNull (result); CollectionAssert.AreEqual (new[] { 1 }, result.Item1); CollectionAssert.AreEqual (new[] { 2 }, result.Item2); CollectionAssert.AreEqual (new[] { "foo" }, result.Item3); }
public void SuccessiveTimeoutTest(HostType hostType, TransportType transportType, MessageBusType messageBusType) { using (var host = CreateHost(hostType, transportType)) { // Arrange var mre = new ManualResetEventSlim(false); host.Initialize(keepAlive: 5, messageBusType: messageBusType); var connection = CreateConnection(host, "/my-reconnect"); using (connection) { connection.Reconnected += () => { mre.Set(); }; connection.Start(host.Transport).Wait(); ((Client.IConnection)connection).KeepAliveData = new KeepAliveData(TimeSpan.FromMilliseconds(500)); // Assert that Reconnected is called Assert.True(mre.Wait(TimeSpan.FromSeconds(15))); // Assert that Reconnected is called again mre.Reset(); Assert.True(mre.Wait(TimeSpan.FromSeconds(15))); // Clean-up mre.Dispose(); } } }
public void BasicUsageTest () { Tuple<int, int> tuple = null; var evt = new ManualResetEventSlim (false); var ablock = new ActionBlock<Tuple<int, int>> (t => { tuple = t; evt.Set (); }); var block = new JoinBlock<int, int> (); block.LinkTo (ablock); block.Target1.Post (42); evt.Wait (1000); Assert.IsNull (tuple); block.Target2.Post (24); evt.Wait (); Assert.IsNotNull (tuple); Assert.AreEqual (42, tuple.Item1); Assert.AreEqual (24, tuple.Item2); }
public void BasicUsageTest() { Tuple<IList<int>, IList<int>> result = null; var evt = new ManualResetEventSlim (false); var actionBlock = new ActionBlock<Tuple<IList<int>, IList<int>>> (r => { result = r; evt.Set (); }); var block = new BatchedJoinBlock<int, int> (2); block.LinkTo (actionBlock); // both targets once Assert.IsTrue (block.Target1.Post (1)); Assert.IsFalse(evt.Wait(100)); Assert.IsNull (result); Assert.IsTrue (block.Target2.Post (2)); Assert.IsTrue (evt.Wait (100)); Assert.IsNotNull (result); CollectionAssert.AreEqual (new[] { 1 }, result.Item1); CollectionAssert.AreEqual (new[] { 2 }, result.Item2); result = null; evt.Reset (); // target 1 twice Assert.IsTrue (block.Target1.Post (3)); Assert.IsFalse(evt.Wait(100)); Assert.IsNull (result); Assert.IsTrue (block.Target1.Post (4)); Assert.IsTrue (evt.Wait (100)); Assert.IsNotNull (result); CollectionAssert.AreEqual (new[] { 3, 4 }, result.Item1); CollectionAssert.IsEmpty (result.Item2); result = null; evt.Reset (); // target 2 twice Assert.IsTrue (block.Target2.Post (5)); Assert.IsFalse(evt.Wait(100)); Assert.IsNull (result); Assert.IsTrue (block.Target2.Post (6)); Assert.IsTrue (evt.Wait (100)); Assert.IsNotNull (result); CollectionAssert.IsEmpty (result.Item1); CollectionAssert.AreEqual (new[] { 5, 6 }, result.Item2); }
public void PushTryPop(int producerThreads, int consumerThreads) { var stack = new ConcurrentStack<int>(); var startEvent = new ManualResetEventSlim(false); var finished = 0; var stop = false; var producerTasks = Enumerable.Range(0, producerThreads).Select(i => Task.Factory.StartNew(() => { var count = iterations/producerThreads; startEvent.Wait(); for (var j = 0; j < count; j++) stack.Push(0); Interlocked.Increment(ref finished); if (finished >= producerThreads) stop = true; }, TaskCreationOptions.LongRunning)).ToArray(); var consumerTasks = Enumerable.Range(0, consumerThreads).Select(i => Task.Factory.StartNew(() => { int num; startEvent.Wait(); while (!stop) stack.TryPop(out num); }, TaskCreationOptions.LongRunning)).ToArray(); var stopwatch = Stopwatch.StartNew(); startEvent.Set(); stop = true; Task.WaitAll(producerTasks); Task.WaitAll(consumerTasks); stopwatch.StopAndLog(iterations); }
public void Execute() { // // 通常の使い方. // var mres = new ManualResetEventSlim(false); ThreadPool.QueueUserWorkItem(DoProc, mres); Output.Write("メインスレッド待機中・・・"); mres.Wait(); Output.WriteLine("終了"); // // WaitメソッドにCancellationTokenを受け付けるオーバーロードを使用。 // mres.Reset(); var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; Task.Factory.StartNew(DoProc, mres); // // キャンセル状態に設定. // tokenSource.Cancel(); Output.Write("メインスレッド待機中・・・"); try { // // CancellationTokenを指定して、Wait呼び出し。 // この場合は、以下のどちらかの条件を満たした時点でWaitが解除される。 // ・別の場所にて、Setが呼ばれてシグナル状態となる。 // ・CancellationTokenがキャンセルされる。 // // トークンがキャンセルされた場合、OperationCanceledExceptionが発生するので // CancellationTokenを指定するWaitを呼び出す場合は、try-catchが必須となる。 // // 今回の例の場合は、予めCancellationTokenをキャンセルしているので // タスク処理でシグナル状態に設定されるよりも先に、キャンセル状態に設定される。 // なので、実行結果には、「*** シグナル状態に設定 ***」という文言は出力されない。 // mres.Wait(token); } catch (OperationCanceledException cancelEx) { Output.Write("*** {0} *** ", cancelEx.Message); } Output.WriteLine("終了"); }
public void TriggerBatchTest () { int[] array = null; var evt = new ManualResetEventSlim (false); var buffer = new BatchBlock<int> (10); var block = new ActionBlock<int[]> (i => { array = i; evt.Set (); }); buffer.LinkTo (block); for (int i = 0; i < 9; i++) Assert.IsTrue (buffer.Post (i)); buffer.TriggerBatch (); evt.Wait (); Assert.IsNotNull (array); Assert.IsTrue (buffer.Post (42)); evt.Wait (1600); CollectionAssert.AreEquivalent (new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, array); }
public void when_sending_message_with_session_then_session_receiver_gets_it() { var sender = this.Settings.CreateTopicClient(this.Topic); var signal = new ManualResetEventSlim(); var body = Guid.NewGuid().ToString(); var receiver = new SessionSubscriptionReceiver(this.Settings, this.Topic, this.Subscription); sender.Send(new BrokeredMessage(Guid.NewGuid().ToString())); sender.Send(new BrokeredMessage(body) { SessionId = "foo" }); var received = ""; receiver.Start( m => { received = m.GetBody<string>(); signal.Set(); return MessageReleaseAction.CompleteMessage; }); signal.Wait(); receiver.Stop(); Assert.Equal(body, received); }
public ETradeDispatcher(Action<Exception> errorHandler) : base(errorHandler) { const int num = 2; //num of Add() calls below var count = 0; var done = new ManualResetEventSlim(false); Action report = delegate { if (Interlocked.Increment(ref count) == num) done.Set(); }; int idmain, iddom; idmain = iddom = 0; Add(() => { idmain = Thread.CurrentThread.ManagedThreadId; report(); }, _eventThreadRequestName); Add(() => { iddom = Thread.CurrentThread.ManagedThreadId; report(); }, _eventThreadResponseName); done.Wait(); _eventThreadRequestId = idmain; _eventThreadResponseId = iddom; }
public static void Test(Action action) { _remain = 100000; var mre = new ManualResetEventSlim(false); action(); while (_remain > 0) mre.Wait(100); }
public void OpenCalledOnConnectionRestored() { int openInvoked = 0; var wh = new ManualResetEventSlim(); var redisConnection = GetMockRedisConnection(); var redisMessageBus = new Mock<RedisMessageBus>(GetDependencyResolver(), new RedisScaleoutConfiguration(String.Empty, String.Empty), redisConnection.Object) { CallBase = true }; redisMessageBus.Setup(m => m.OpenStream(It.IsAny<int>())).Callback(() => { // Open would be called twice - once when connection starts and once when it is restored if (++openInvoked == 2) { wh.Set(); } }); // Creating an instance to invoke the constructor which starts the connection var instance = redisMessageBus.Object; redisConnection.Raise(mock => mock.ConnectionRestored += null, new Exception()); Assert.True(wh.Wait(TimeSpan.FromSeconds(5))); }
public void MarkActiveStopsConnectionIfCalledAfterExtendedPeriod(HostType hostType, TransportType transportType, MessageBusType messageBusType) { using (var host = CreateHost(hostType, transportType)) { host.Initialize(messageBusType: messageBusType); var connection = CreateHubConnection(host); using (connection) { var disconnectWh = new ManualResetEventSlim(); connection.Closed += () => { disconnectWh.Set(); }; connection.Start(host.Transport).Wait(); // The MarkActive interval should check the reconnect window. Since this is short it should force the connection to disconnect. ((Client.IConnection)connection).ReconnectWindow = TimeSpan.FromSeconds(1); Assert.True(disconnectWh.Wait(TimeSpan.FromSeconds(15)), "Closed never fired"); } } }
public void Ctor_ThrowsAnException_IfLockCanNotBeGranted() { var releaseLock = new ManualResetEventSlim(false); var lockAcquired = new ManualResetEventSlim(false); var thread = new Thread( () => UseConnection(connection1 => { var storage = CreateStorage(connection1); using (new SqlServerDistributedLock(storage, "exclusive", _timeout)) { lockAcquired.Set(); releaseLock.Wait(); } })); thread.Start(); lockAcquired.Wait(); UseConnection(connection2 => { var storage = CreateStorage(connection2); Assert.Throws<DistributedLockTimeoutException>( () => { using (new SqlServerDistributedLock(storage, "exclusive", _timeout)) { } }); }); releaseLock.Set(); thread.Join(); }
public async Task WebSocketSendReceiveTest() { const int MessageCount = 3; var sentMessages = new List<string>(); var receivedMessages = new List<string>(); using (var hubConnection = new HubConnection(HubUrl)) { var wh = new ManualResetEventSlim(); var proxy = hubConnection.CreateHubProxy("StoreWebSocketTestHub"); proxy.On<string>("echo", m => { receivedMessages.Add(m); if (receivedMessages.Count == MessageCount) { wh.Set(); } }); await hubConnection.Start(new WebSocketTransport()); for (var i = 0; i < MessageCount; i++) { var message = "MyMessage" + i; await proxy.Invoke("Echo", message); sentMessages.Add(message); } await Task.Run(() => wh.Wait(5000)); } Assert.Equal(sentMessages, receivedMessages); }
private static void Main(string[] args) { var taskOne = Task.Factory.StartNew(() => { Console.WriteLine("Task 1 is starting..."); Thread.Sleep(5000); ManualResetEventSlim.Set(); Console.WriteLine("Task 1 is completed."); }); var taskTwo = Task.Factory.StartNew(() => { Console.WriteLine("Task 2 waiting for Task 1 to complete..."); ManualResetEventSlim.Wait(); Console.WriteLine("Task 2 is started..."); Console.WriteLine("All tasks are completed"); }); taskTwo.Wait(); Console.ReadLine(); }
private bool RawSendHelper(byte[] aData, bool aWait) { if (IsInBackgroundThread) { return SendRawData(aData); } if (!IsConnected) { return false; } if (aWait) { using (var xEvent = new ManualResetEventSlim(false)) { mPendingWrites.Add(new Outgoing {Packet = aData, Completed = xEvent}); while (IsConnected) { if (xEvent.Wait(25)) { break; } } return IsConnected; // ?? } } else { mPendingWrites.Add(new Outgoing {Packet = aData}); return true; } }
public static IDisposable RunConnectDisconnect(int connections) { var host = new MemoryHost(); host.MapHubs(); for (int i = 0; i < connections; i++) { var connection = new Client.Hubs.HubConnection("http://foo"); var proxy = connection.CreateHubProxy("EchoHub"); var wh = new ManualResetEventSlim(false); proxy.On("echo", _ => wh.Set()); try { connection.Start(host).Wait(); proxy.Invoke("Echo", "foo").Wait(); if (!wh.Wait(TimeSpan.FromSeconds(10))) { Debugger.Break(); } } finally { connection.Stop(); } } return host; }
public void BackgroundHttpRequester_StopAsync_Stops_Current_Active_Request() { var cancelled = false; var mre = new ManualResetEventSlim(); Func<Uri, CancellationToken, bool> processor = (u, c) => { try { mre.Wait(c); } catch (AggregateException) { } catch (OperationCanceledException) { } mre.Set(); cancelled = c.IsCancellationRequested; return true; }; var requester = new BackgroundHttpFuncRequester(processor); requester.Add(TestHelpers.CreateRequestList(1)[0]); requester.Start(TimeSpan.FromMilliseconds(10)); Assert.IsFalse(cancelled); requester.StopAsync().Wait(3000); Assert.IsTrue(mre.Wait(3000)); Assert.IsTrue(cancelled); }
// Demonstrates: // ManualResetEventSlim construction // ManualResetEventSlim.Wait() // ManualResetEventSlim.Set() // ManualResetEventSlim.Reset() // ManualResetEventSlim.IsSet static void MRES_SetWaitReset() { System.Threading.ManualResetEventSlim mres1 = new System.Threading.ManualResetEventSlim(false); // initialize as unsignaled System.Threading.ManualResetEventSlim mres2 = new System.Threading.ManualResetEventSlim(false); // initialize as unsignaled System.Threading.ManualResetEventSlim mres3 = new System.Threading.ManualResetEventSlim(true); // initialize as signaled // Start an asynchronous Task that manipulates mres3 and mres2 var observer = Task.Factory.StartNew(() => { mres1.Wait(); Console.WriteLine("observer sees signaled mres1!"); Console.WriteLine("observer resetting mres3..."); mres3.Reset(); // should switch to unsignaled Console.WriteLine("observer signalling mres2"); mres2.Set(); }); Console.WriteLine("main thread: mres3.IsSet = {0} (should be true)", mres3.IsSet); Console.WriteLine("main thread signalling mres1"); mres1.Set(); // This will "kick off" the observer Task mres2.Wait(); // This won't return until observer Task has finished resetting mres3 Console.WriteLine("main thread sees signaled mres2!"); Console.WriteLine("main thread: mres3.IsSet = {0} (should be false)", mres3.IsSet); // It's good form to Dispose() a ManualResetEventSlim when you're done with it observer.Wait(); // make sure that this has fully completed mres1.Dispose(); mres2.Dispose(); mres3.Dispose(); }
static void PrintFooBar(int p) { System.Threading.ManualResetEventSlim mres = new System.Threading.ManualResetEventSlim(false); // initialize as unsignaled System.Threading.ManualResetEventSlim mres2 = new System.Threading.ManualResetEventSlim(true); // initialize as unsignaled Thread t1 = new Thread(() => { for (int i = 0; i < 20; i++) { mres2.Wait(); Console.WriteLine("foo"); mres2.Reset(); mres.Set(); } } ); t1.Start(); Thread t2 = new Thread(() => { for (int i = 0; i < 20; i++) { mres.Wait();//true Console.WriteLine("bar"); mres.Reset(); mres2.Set(); } }); t2.Start(); }
public void UseSqlNotificationsIfAvailable(bool supportSqlNotifications) { // Arrange var sqlDependencyAdded = false; var retryLoopCount = 0; var mre = new ManualResetEventSlim(); var dbProviderFactory = new MockDbProviderFactory(); var dbBehavior = new Mock<IDbBehavior>(); dbBehavior.Setup(db => db.UpdateLoopRetryDelays).Returns(_defaultRetryDelays); dbBehavior.Setup(db => db.StartSqlDependencyListener()).Returns(supportSqlNotifications); dbBehavior.Setup(db => db.AddSqlDependency(It.IsAny<IDbCommand>(), It.IsAny<Action<SqlNotificationEventArgs>>())) .Callback(() => { sqlDependencyAdded = true; mre.Set(); }); var operation = new ObservableDbOperation("test", "test", new TraceSource("test"), dbProviderFactory, dbBehavior.Object); operation.Faulted += _ => mre.Set(); operation.Queried += () => { retryLoopCount++; if (retryLoopCount > 1) { mre.Set(); } }; // Act ThreadPool.QueueUserWorkItem(_ => operation.ExecuteReaderWithUpdates((record, o) => { })); mre.Wait(); operation.Dispose(); // Assert Assert.Equal(supportSqlNotifications, sqlDependencyAdded); }
/// <summary> /// Joins an IRC channel. Only one channel is supported at a time. /// </summary> /// <param name="channel"></param> public void Join(string channel) { // Leave current channel lock (_lockobject) { if (!String.IsNullOrEmpty(_currentChannel) && _state == ConnectionState.ChannelJoined) { WriteToServerStream($"PART {_currentChannel}"); _state = ConnectionState.Connected; } } _LookingforServerResponseEvent.Reset(); if (!channel.StartsWith("#")) { channel = "#" + channel; } WriteToServerStream($"JOIN {channel}"); _LookingforServerResponse = true; _LookingforServerResponseCode = 366; _LookingforServerResponseEvent.Wait(); // Successfully joined _currentChannel = channel; lock (_lockobject) { _state = ConnectionState.ChannelJoined; } }
public void events_raised_whilst_consuming_events_should_be_recorded() { var waitForConsumption = new ManualResetEventSlim(false); Transaction consumerTransaction = null; var eventStore = Substitute.For<EventStore>(); //Because consumers run in background threads, we need to block until complete before we assert. eventStore.When(_ => _.LogConsumption(Arg.Any<RaisedEvent>(), Arg.Any<ConsumptionLog>())).Do(info => { consumerTransaction = Transaction.Current; waitForConsumption.Set(); }); var domain = new TestableDomain(null, null, eventStore); var key = "test"; domain.Consume( new RaisedEvent( new DogRegistered(key, null), DateTimeOffset.UtcNow)); waitForConsumption.Wait(); var aggregateInfo = domain.AggregateTracker[typeof (Dog), key]; ((string) aggregateInfo.Instance.AsDynamic().earbrand).ShouldEqual(key); aggregateInfo.Lifestate.ShouldEqual(AggregateLifestate.Live); var recorded = domain.TransactionTracker[consumerTransaction].RecordedEvents; recorded.Count().ShouldEqual(1); recorded.First().Event.ShouldBeType<DogIsNotVaccinated>(); }
public override void Respond(IHttpContext context) { if (string.IsNullOrEmpty(context.Request.QueryString["no-op"]) == false) { // this is a no-op request which is there just to force the client HTTP layer to handle the authentication // only used for legacy clients return; } if("generate-single-use-auth-token".Equals(context.Request.QueryString["op"],StringComparison.InvariantCultureIgnoreCase)) { // using windows auth with anonymous access = none sometimes generate a 401 even though we made two requests // instead of relying on windows auth, which require request buffering, we generate a one time token and return it. // we KNOW that the user have access to this db for writing, since they got here, so there is no issue in generating // a single use token for them. var token = server.RequestAuthorizer.GenerateSingleUseAuthToken(Database, context.User); context.WriteJson(new { Token = token }); return; } if (HttpContext.Current != null) { HttpContext.Current.Server.ScriptTimeout = 60*60*6; // six hours should do it, I think. } var options = new BulkInsertOptions { CheckForUpdates = context.GetCheckForUpdates(), CheckReferencesInIndexes = context.GetCheckReferencesInIndexes() }; var operationId = ExtractOperationId(context); var sp = Stopwatch.StartNew(); var status = new BulkInsertStatus(); int documents = 0; var mre = new ManualResetEventSlim(false); var currentDatbase = Database; var task = Task.Factory.StartNew(() => { currentDatbase.BulkInsert(options, YieldBatches(context, mre, batchSize => documents += batchSize), operationId); status.Documents = documents; status.Completed = true; }); long id; Database.AddTask(task, status, out id); mre.Wait(Database.WorkContext.CancellationToken); context.Log(log => log.Debug("\tBulk inserted received {0:#,#;;0} documents in {1}, task #: {2}", documents, sp.Elapsed, id)); context.WriteJson(new { OperationId = id }); }
public async Task CanInvokeMethodsAndReceiveMessagesFromValidTypedHub(HostType hostType, TransportType transportType, MessageBusType messageBusType) { using (var host = CreateHost(hostType, transportType)) { host.Initialize(messageBusType: messageBusType); using (var connection = CreateHubConnection(host)) { var hub = connection.CreateHubProxy("ValidTypedHub"); var echoTcs = new TaskCompletionSource<string>(); var pingWh = new ManualResetEventSlim(); hub.On<string>("Echo", message => echoTcs.TrySetResult(message)); hub.On("Ping", pingWh.Set); await connection.Start(host.TransportFactory()); hub.InvokeWithTimeout("Echo", "arbitrary message"); Assert.True(echoTcs.Task.Wait(TimeSpan.FromSeconds(10))); Assert.Equal("arbitrary message", echoTcs.Task.Result); hub.InvokeWithTimeout("Ping"); Assert.True(pingWh.Wait(TimeSpan.FromSeconds(10))); } } }
public void DisconnectFiresForHubsWhenConnectionGoesAway() { using (var host = new MemoryHost()) { host.MapHubs(); host.Configuration.DisconnectTimeout = TimeSpan.Zero; host.Configuration.HeartbeatInterval = TimeSpan.FromSeconds(5); var connectWh = new ManualResetEventSlim(); var disconnectWh = new ManualResetEventSlim(); host.DependencyResolver.Register(typeof(MyHub), () => new MyHub(connectWh, disconnectWh)); var connection = new Client.Hubs.HubConnection("http://foo/"); connection.CreateHubProxy("MyHub"); // Maximum wait time for disconnect to fire (3 heart beat intervals) var disconnectWait = TimeSpan.FromTicks(host.Configuration.HeartbeatInterval.Ticks * 3); connection.Start(host).Wait(); Assert.True(connectWh.Wait(TimeSpan.FromSeconds(10)), "Connect never fired"); connection.Stop(); Assert.True(disconnectWh.Wait(disconnectWait), "Disconnect never fired"); } }
static void DoWork(CancellationToken token) { while (true) { if (token.IsCancellationRequested) { Console.WriteLine("Canceled while running."); token.ThrowIfCancellationRequested(); } // Wait on the event to be signaled // or the token to be canceled, // whichever comes first. The token // will throw an exception if it is canceled // while the thread is waiting on the event. try { // mres is a ManualResetEventSlim mres.Wait(token); } catch (OperationCanceledException) { // Throw immediately to be responsive. The // alternative is to do one more item of work, // and throw on next iteration, because // IsCancellationRequested will be true. Console.WriteLine("The wait operation was canceled."); throw; } Console.Write("Working..."); // Simulating work. Thread.SpinWait(500000); } }
public void When_command_committed_CompletionTaskSource_is_notified() { const int CommandCount = 5; var leader = CreateNetworkAndGetLeader(3); var commands = Builder<DictionaryCommand.Set>.CreateListOfSize(CommandCount) .All() .With(x => x.Completion = new TaskCompletionSource<object>()) .With(x => x.AssignedIndex = -1) .Build() .ToList(); var nonLeaderNode = Nodes.First(x => x.State != RaftEngineState.Leader); var commitsAppliedEvent = new ManualResetEventSlim(); nonLeaderNode.CommitIndexChanged += (oldIndex, newIndex) => { //CommandCount + 1 --> take into account NOP command that leader sends after election if (newIndex == CommandCount + 1) commitsAppliedEvent.Set(); }; commands.ForEach(leader.AppendCommand); Assert.True(commitsAppliedEvent.Wait(nonLeaderNode.Options.ElectionTimeout * 2)); commands.Should().OnlyContain(cmd => cmd.Completion.Task.Status == TaskStatus.RanToCompletion); }
public void when_sending_message_then_can_receive_it() { var sender = new TopicSender(this.Settings, this.Topic); Data data = new Data { Id = Guid.NewGuid(), Title = "Foo" }; Data received = null; using (var receiver = new SubscriptionReceiver(this.Settings, this.Topic, this.Subscription)) { var signal = new ManualResetEventSlim(); receiver.Start( m => { received = m.GetBody<Data>(); signal.Set(); return MessageReleaseAction.CompleteMessage; }); sender.SendAsync(() => new BrokeredMessage(data)); signal.Wait(); } Assert.NotNull(received); Assert.Equal(data.Id, received.Id); Assert.Equal(data.Title, received.Title); }
public async void ConnectRetriesOnError() { int invokationCount = 0; var wh = new ManualResetEventSlim(); var redisConnection = GetMockRedisConnection(); var tcs = new TaskCompletionSource<object>(); tcs.TrySetCanceled(); redisConnection.Setup(m => m.ConnectAsync(It.IsAny<string>(), It.IsAny<TraceSource>())).Returns<string, TraceSource>((connectionString, trace) => { if (++invokationCount == 2) { wh.Set(); return Task.FromResult(0); } else { return tcs.Task; } }); var redisMessageBus = new RedisMessageBus(GetDependencyResolver(), new RedisScaleoutConfiguration(String.Empty, String.Empty), redisConnection.Object, false); await redisMessageBus.ConnectWithRetry(); Assert.True(wh.Wait(TimeSpan.FromSeconds(5))); Assert.Equal(RedisMessageBus.State.Connected, redisMessageBus.ConnectionState); }
public void ConnectionErrorCapturesExceptionsThrownInClientHubMethod(HostType hostType, TransportType transportType) { using (var host = CreateHost(hostType, transportType)) { var wh = new ManualResetEventSlim(); Exception thrown = new Exception(), caught = null; host.Initialize(); var connection = CreateHubConnection(host); var proxy = connection.CreateHubProxy("ChatHub"); proxy.On("addMessage", () => { throw thrown; }); connection.Error += e => { caught = e; wh.Set(); }; connection.Start(host.Transport).Wait(); proxy.Invoke("Send", ""); Assert.True(wh.Wait(TimeSpan.FromSeconds(5))); Assert.Equal(thrown, caught); } }
/// <summary> /// Blocking wait for a task, equivalent to calling Task.Wait(), /// but works around a race in Mono that causes Wait() to hang /// </summary> /// <param name="task">The task to wait for</param> /// <returns>The task</returns> public static Task WaitForTask(this Task task) { // Mono has a race when waiting for a // task to complete, this workaround // ensures that the wait call does not hang if (IsRunningMono) { if (!task.IsCompleted) { using (var lck = new System.Threading.ManualResetEventSlim(false)) { task.ContinueWith(x => lck.Set()); // This ensures we never return with // an incomplete task, but may casue // some spin waiting while (!task.IsCompleted) { lck.Wait(); } } } } else { try { task.Wait(); } catch { // Don't throw the exception here // let the caller access the task } } return(task); }
public void TestAllow() { var configSource = StartBootstrap("ConnectionFilter.config"); var serverConfig = configSource.Servers.FirstOrDefault(); var appServer = BootStrap.AppServers.FirstOrDefault() as TestServer; appServer.NewSessionConnected += m_Server_NewSessionConnected; EndPoint serverAddress = new IPEndPoint(IPAddress.Parse("127.0.0.1"), serverConfig.Port); using (Socket socket = new Socket(serverAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) { TestConnectionFilter.Allow = true; int oldCount = TestConnectionFilter.ConnectedCount; var signal = new ManualResetEventSlim(false); ThreadPool.QueueUserWorkItem((o) => { var s = o as Socket; s.Connect(serverAddress); signal.Set(); }, socket); Assert.IsTrue(signal.Wait(2000)); Thread.Sleep(100); Assert.AreEqual(oldCount + 1, TestConnectionFilter.ConnectedCount); if (!m_NewSessionConnectedEvent.WaitOne(1000)) Assert.Fail("New session hasnot been accept on time!"); } }
[Test] // bug https://bugzilla.novell.com/show_bug.cgi?id=325368 public void EnabledInElapsed() { var elapsedCount = 0; var mre = new ST.ManualResetEventSlim(); timer = new Timer(50); timer.AutoReset = false; timer.Elapsed += (s, e) => { elapsedCount++; if (elapsedCount == 1) { timer.Enabled = true; } else if (elapsedCount == 2) { mre.Set(); } }; timer.Start(); Assert.IsTrue(mre.Wait(1000), "#1 re-enabling timer in Elapsed didn't work"); Assert.AreEqual(2, elapsedCount, "#2 wrong elapsedCount"); timer.Stop(); }
public void Can_create_actor_using_remote_daemon_and_interact_with_child() { var p = CreateTestProbe(); Sys.EventStream.Subscribe(p.Ref, typeof(string)); var supervisor = Sys.ActorOf<SomeActor>(); var provider = (RemoteActorRefProvider)((ActorSystemImpl)Sys).Provider; var daemon = provider.RemoteDaemon; var childCreatedEvent=new ManualResetEventSlim(); var path = (((ActorSystemImpl)Sys).Guardian.Path.Address + "/remote/user/foo").ToString(); //ask to create an actor MyRemoteActor, this actor has a child "child" daemon.Tell(new DaemonMsgCreate(Props.Create(() => new MyRemoteActor(childCreatedEvent)), null, path, supervisor)); //Wait for the child to be created (actors are instantiated async) childCreatedEvent.Wait(); //try to resolve the child actor "child" var child = provider.ResolveActorRef(provider.RootPath / "remote/user/foo/child".Split('/')); //pass a message to the child child.Tell("hello"); //expect the child to forward the message to the eventstream p.ExpectMsg("hello"); }
public void Start() { try { slim.Wait(); slim.Reset(); } finally { slim.Set(); } }
private static void ClientConnect() { using (var client = new AsyncSocketConnector()) using (var ready = new System.Threading.ManualResetEventSlim(false)) { client.FilterChain.AddLast("ssl", new SslFilter("TempCert", null)); client.FilterChain.AddLast("text", new ProtocolCodecFilter(new TextLineCodecFactory())); client.MessageReceived += (s, e) => { Debug.WriteLine("Client got: " + e.Message); ready.Set(); }; var session = client.Connect(new IPEndPoint(IPAddress.Loopback, port)).Await().Session; Debug.WriteLine("Client sending: hello"); session.Write("hello "); Debug.WriteLine("Client sending: send"); session.Write("send"); ready.Wait(3000); Assert.IsTrue(ready.IsSet); ready.Reset(); Assert.IsFalse(ready.IsSet); Debug.WriteLine("Client sending: hello"); session.Write(IoBuffer.Wrap(Encoding.UTF8.GetBytes("hello \n"))); Debug.WriteLine("Client sending: send"); session.Write(IoBuffer.Wrap(Encoding.UTF8.GetBytes("send\n"))); ready.Wait(3000); Assert.IsTrue(ready.IsSet); session.Close(true); } }
public bool WaitForWorkItems(double timeout) { if (_Disposed) { return(false); } if (_Queue.Count > 0) { return(true); } else { Interlocked.Increment(ref _WaiterCount); if (timeout <= 0) { timeout = DefaultWaitTimeout; } int timeoutMs = (int)Math.Ceiling(TimeSpan.FromSeconds(timeout).TotalMilliseconds); try { if (_Queue.Count > 0) { return(true); } else { var result = _WaiterSignal.Wait(timeoutMs); if (_Disposed) { return(false); } else { _WaiterSignal.Reset(); return(result); } } } finally { Interlocked.Decrement(ref _WaiterCount); } } }
public void AutoResetEventFalseStopsFiringElapsed () { var elapsedCount = 0; var mre = new ST.ManualResetEventSlim (); timer = new Timer (50); timer.AutoReset = false; timer.Elapsed += (s, e) => { elapsedCount++; if (elapsedCount > 1) mre.Set (); }; timer.Start (); Assert.IsFalse (mre.Wait (1000), "#1 AutoReset=false didn't stop firing Elapsed, elapsedCount=" + elapsedCount); Assert.AreEqual (1, elapsedCount, "#2 wrong elapsedCount"); timer.Stop (); }
public virtual bool TryGetResponse(out string response, int millisecondsTimeout) { var mre = new System.Threading.ManualResetEventSlim(false); string resp = response = null; ThreadPool.QueueUserWorkItem(_ => { resp = GetResponse(); mre.Set(); }); if (mre.Wait(millisecondsTimeout)) { response = resp; return(true); } else { return(false); } }
public override void Send(SendOrPostCallback d, object state) { if (Thread.CurrentThread != m_thread) { using (var signal = new System.Threading.ManualResetEventSlim()) { Post( (s) => { d(s); signal.Set(); }, state ); signal.Wait(); } } else { d(state); } }
public bool TryEnterWriteLock(int millisecondsTimeout) { var currentThreadState = CurrentThreadState; if (CheckState(currentThreadState, millisecondsTimeout, LockState.Write)) { ++currentThreadState.WriterRecursiveCount; return(true); } ++WaitingWriteCount; var isUpgradable = (currentThreadState.LockState & LockState.Upgradable) > 0; var registered = false; var success = false; RuntimeHelpers.PrepareConstrainedRegions(); try { /* If the code goes there that means we had a read lock beforehand * that need to be suppressed, we also take the opportunity to register * our interest in the write lock to avoid other write wannabe process * coming in the middle */ if (isUpgradable && _rwLock >= _rwRead) { try { // Empty } finally { if (Interlocked.Add(ref _rwLock, _rwWaitUpgrade - _rwRead) >> _rwReadBit == 0) { _readerDoneEvent.Set(); } registered = true; } } var stateCheck = isUpgradable ? _rwWaitUpgrade + _rwWait : _rwWait; var start = millisecondsTimeout == -1 ? 0 : _stopwatch.ElapsedMilliseconds; var registration = isUpgradable ? _rwWaitUpgrade : _rwWait; do { var state = _rwLock; if (state <= stateCheck) { try { // Empty } finally { var toWrite = state + _rwWrite - (registered ? registration : 0); if (Interlocked.CompareExchange(ref _rwLock, toWrite, state) == state) { _writerDoneEvent.Reset(); currentThreadState.LockState ^= LockState.Write; ++currentThreadState.WriterRecursiveCount; --WaitingWriteCount; registered = false; success = true; } } if (success) { return(true); } } state = _rwLock; // We register our interest in taking the Write lock (if upgradeable it's already done) if (!isUpgradable) { while ((state & _rwWait) == 0) { try { // Empty } finally { registered |= Interlocked.CompareExchange(ref _rwLock, state | _rwWait, state) == state; } if (registered) { break; } state = _rwLock; } } // Before falling to sleep do { if (_rwLock <= stateCheck) { break; } if ((_rwLock & _rwWrite) != 0) { _writerDoneEvent.Wait(ComputeTimeout(millisecondsTimeout, start)); } else if (_rwLock >> _rwReadBit > 0) { _readerDoneEvent.Wait(ComputeTimeout(millisecondsTimeout, start)); } } while (millisecondsTimeout < 0 || _stopwatch.ElapsedMilliseconds - start < millisecondsTimeout); } while (millisecondsTimeout < 0 || _stopwatch.ElapsedMilliseconds - start < millisecondsTimeout); --WaitingWriteCount; } finally { if (registered) { Interlocked.Add(ref _rwLock, isUpgradable ? -_rwWaitUpgrade : -_rwWait); } } return(false); }
// // Taking the Upgradable read lock is like taking a read lock // but we limit it to a single upgradable at a time. // public bool TryEnterUpgradeableReadLock(int millisecondsTimeout) { var currentThreadState = CurrentThreadState; if (CheckState(currentThreadState, millisecondsTimeout, LockState.Upgradable)) { ++currentThreadState.UpgradeableRecursiveCount; return(true); } if ((currentThreadState.LockState & LockState.Read) > 0) { throw new LockRecursionException("The current thread has already entered read mode"); } ++WaitingUpgradeCount; var start = millisecondsTimeout == -1 ? 0 : _stopwatch.ElapsedMilliseconds; var taken = false; var success = false; // We first try to obtain the upgradeable right try { // ReSharper disable once ConditionIsAlwaysTrueOrFalse while (!_upgradableEvent.IsSet || !taken) { try { // Empty } finally { taken = _upgradableTaken.TryRelaxedSet(); } if (taken) { break; } if (millisecondsTimeout != -1 && _stopwatch.ElapsedMilliseconds - start > millisecondsTimeout) { --WaitingUpgradeCount; return(false); } _upgradableEvent.Wait(ComputeTimeout(millisecondsTimeout, start)); } _upgradableEvent.Reset(); RuntimeHelpers.PrepareConstrainedRegions(); try { // Then it's a simple reader lock acquiring TryEnterReadLock(ComputeTimeout(millisecondsTimeout, start), ref success); } finally { if (success) { currentThreadState.LockState |= LockState.Upgradable; currentThreadState.LockState &= ~LockState.Read; --currentThreadState.ReaderRecursiveCount; ++currentThreadState.UpgradeableRecursiveCount; } else { _upgradableTaken.Value = false; _upgradableEvent.Set(); } } --WaitingUpgradeCount; } catch (Exception ex) { No.Op(ex); // An async exception occured, if we had taken the upgradable mode, release it _upgradableTaken.Value &= !taken || success; } return(success); }
private bool TryEnterReadLock(int millisecondsTimeout, ref bool success) { var ctstate = CurrentThreadState; if (CheckState(ctstate, millisecondsTimeout, LockState.Read)) { ++ctstate.ReaderRecursiveCount; return(true); } // This is downgrading from upgradable, no need for check since // we already have a sort-of read lock that's going to disappear // after user calls ExitUpgradeableReadLock. // Same idea when recursion is allowed and a write thread wants to // go for a Read too. if (ctstate.LockState.Has(LockState.Upgradable) || (!_noRecursion && ctstate.LockState.Has(LockState.Write))) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { Interlocked.Add(ref _rwlock, _rwRead); ctstate.LockState |= LockState.Read; ++ctstate.ReaderRecursiveCount; success = true; } return(true); } _numReadWaiters++; int val; var start = millisecondsTimeout == -1 ? 0 : _stopwatch.ElapsedMilliseconds; do { /* Check if a writer is present (RwWrite) or if there is someone waiting to * acquire a writer lock in the queue (RwWait | RwWaitUpgrade). */ if ((_rwlock & (_rwWrite | _rwWait | _rwWaitUpgrade)) > 0) { _writerDoneEvent.Wait(ComputeTimeout(millisecondsTimeout, start)); continue; } /* Optimistically try to add ourselves to the reader value * if the adding was too late and another writer came in between * we revert the operation. */ RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (((val = Interlocked.Add(ref _rwlock, _rwRead)) & (_rwWrite | _rwWait | _rwWaitUpgrade)) == 0) { /* If we are the first reader, reset the event to let other threads * sleep correctly if they try to acquire write lock */ if (val >> _rwReadBit == 1) { _readerDoneEvent.Reset(); } ctstate.LockState ^= LockState.Read; ++ctstate.ReaderRecursiveCount; --_numReadWaiters; success = true; } else { Interlocked.Add(ref _rwlock, -_rwRead); } } if (success) { return(true); } _writerDoneEvent.Wait(ComputeTimeout(millisecondsTimeout, start)); } while (millisecondsTimeout == -1 || (_stopwatch.ElapsedMilliseconds - start) < millisecondsTimeout); --_numReadWaiters; return(false); }
// // Taking the Upgradable read lock is like taking a read lock // but we limit it to a single upgradable at a time. // public bool TryEnterUpgradeableReadLock(int millisecondsTimeout) { ThreadLockState ctstate = CurrentThreadState; if (CheckState(ctstate, millisecondsTimeout, LockState.Upgradable)) { ++ctstate.UpgradeableRecursiveCount; return(true); } if (ctstate.LockState.Has(LockState.Read)) { throw new LockRecursionException("The current thread has already entered read mode"); } ++numUpgradeWaiters; long start = millisecondsTimeout == -1 ? 0 : sw.ElapsedMilliseconds; bool taken = false; bool success = false; // We first try to obtain the upgradeable right try { while (!upgradableEvent.IsSet() || !taken) { try {} finally { taken = upgradableTaken.TryRelaxedSet(); } if (taken) { break; } if (millisecondsTimeout != -1 && (sw.ElapsedMilliseconds - start) > millisecondsTimeout) { --numUpgradeWaiters; return(false); } upgradableEvent.Wait(ComputeTimeout(millisecondsTimeout, start)); } upgradableEvent.Reset(); RuntimeHelpers.PrepareConstrainedRegions(); try { // Then it's a simple reader lock acquiring TryEnterReadLock(ComputeTimeout(millisecondsTimeout, start), ref success); } finally { if (success) { ctstate.LockState |= LockState.Upgradable; ctstate.LockState &= ~LockState.Read; --ctstate.ReaderRecursiveCount; ++ctstate.UpgradeableRecursiveCount; } else { upgradableTaken.Value = false; upgradableEvent.Set(); } } --numUpgradeWaiters; } catch { // An async exception occured, if we had taken the upgradable mode, release it if (taken && !success) { upgradableTaken.Value = false; } } return(success); }
internal void SleepWorkerThreadFunc(PriorityQueue <SleepItem> pendingSleeps, System.Threading.ManualResetEventSlim newSleepEvent) { while (true) { long now = TimeProvider.Ticks; SleepItem currentSleep; Monitor.Enter(pendingSleeps); if (pendingSleeps.Peek(out currentSleep)) { if (currentSleep.Tick(now)) { pendingSleeps.Dequeue(); Monitor.Exit(pendingSleeps); continue; } else { Monitor.Exit(pendingSleeps); } } else { Monitor.Exit(pendingSleeps); if (!newSleepEvent.Wait(SleepThreadTimeoutMs)) { return; } newSleepEvent.Reset(); continue; } long sleepUntil = currentSleep.Until; now = TimeProvider.Ticks; long timeToSleep = (sleepUntil - now) + SleepFudgeFactor; if (timeToSleep < SleepSpinThreshold) { int iteration = 1; while (TimeProvider.Ticks < sleepUntil) { Thread.SpinWait(20 * iteration); iteration += 1; } timeToSleep = 0; } if (timeToSleep > 0) { if (timeToSleep > MaximumSleepLength) { timeToSleep = MaximumSleepLength; } int msToSleep = 0; if (timeToSleep >= MinimumSleepLength) { msToSleep = (int)(timeToSleep / Time.MillisecondInTicks); } if (newSleepEvent != null) { newSleepEvent.Reset(); newSleepEvent.Wait(msToSleep); } } } }
/// <summary> /// Notifies the <see cref="Barrier"/> that there will be additional participants. /// </summary> /// <param name="participantCount">The number of additional participants to add to the /// barrier.</param> /// <returns>The phase number of the barrier in which the new participants will first /// participate.</returns> /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="participantCount"/> is less than /// 0.</exception> /// <exception cref="T:System.ArgumentOutOfRangeException">Adding <paramref name="participantCount"/> participants would cause the /// barrier's participant count to exceed <see cref="T:System.Int16.MaxValue"/>.</exception> /// <exception cref="T:System.InvalidOperationException"> /// The method was invoked from within a post-phase action. /// </exception> /// <exception cref="T:System.ObjectDisposedException">The current instance has already been /// disposed.</exception> public long AddParticipants(int participantCount) { // check dispose ThrowIfDisposed(); if (participantCount < 1) { throw new ArgumentOutOfRangeException("participantCount", participantCount, "The participantCount argument must be a positive value."); } else if (participantCount > Max_Participants) //overflow { throw new ArgumentOutOfRangeException("participantCount", "Adding participantCount participants would result in the number of participants exceeding the maximum number allowed."); } // in case of this is called from the PHA if (_actionCallerId != 0 && Thread.CurrentThread.ManagedThreadId == _actionCallerId) { throw new InvalidOperationException("This method may not be called from within the postPhaseAction."); } var spinner = new SpinWait(); long newPhase; while (true) { var currentTotal = Thread.VolatileRead(ref _currentTotalCount); int total; int current; bool sense; GetCurrentTotal(currentTotal, out current, out total, out sense); if (participantCount + total > Max_Participants) //overflow { throw new ArgumentOutOfRangeException("participantCount", "Adding participantCount participants would result in the number of participants exceeding the maximum number allowed."); } if (SetCurrentTotal(currentTotal, current, total + participantCount, sense)) { // Calculating the first phase for that participant, if the current phase already finished return the nextphase else return the current phase // To know that the current phase is the sense doesn't match the // phase odd even, so that means it didn't yet change the phase count, so currentPhase +1 is returned, otherwise currentPhase is returned var currPhase = CurrentPhaseNumber; newPhase = (sense != (currPhase % 2 == 0)) ? currPhase + 1 : currPhase; // If this participant is going to join the next phase, which means the postPhaseAction is being running, this participants must wait until this done // and its event is reset. // Without that, if the postPhaseAction takes long time, this means the event ehich the current participant is goint to wait on is still set // (FinishPPhase didn't reset it yet) so it should wait until it reset if (newPhase != currPhase) { // Wait on the opposite event if (sense) { _oddEvent.Wait(); } else { _evenEvent.Wait(); } } //This else to fix the racing where the current phase has been finished, m_currentPhase has been updated but the events have not been set/reset yet // otherwise when this participant calls SignalAndWait it will wait on a set event however all other participants have not arrived yet. else { if (sense && _evenEvent.IsSet) { _evenEvent.Reset(); } else if (!sense && _oddEvent.IsSet) { _oddEvent.Reset(); } } break; } spinner.SpinOnce(); } return(newPhase); }
public bool TryEnterWriteLock(int millisecondsTimeout) { ThreadLockState ctstate = CurrentThreadState; if (CheckState(ctstate, millisecondsTimeout, LockState.Write)) { ++ctstate.WriterRecursiveCount; return(true); } ++numWriteWaiters; bool isUpgradable = ctstate.LockState.Has(LockState.Upgradable); bool registered = false; bool success = false; RuntimeHelpers.PrepareConstrainedRegions(); try { /* If the code goes there that means we had a read lock beforehand * that need to be suppressed, we also take the opportunity to register * our interest in the write lock to avoid other write wannabe process * coming in the middle */ if (isUpgradable && rwlock >= RwRead) { try {} finally { if (Interlocked.Add(ref rwlock, RwWaitUpgrade - RwRead) >> RwReadBit == 0) { readerDoneEvent.Set(); } registered = true; } } int stateCheck = isUpgradable ? RwWaitUpgrade + RwWait : RwWait; long start = millisecondsTimeout == -1 ? 0 : sw.ElapsedMilliseconds; do { int state = rwlock; if (state <= stateCheck) { try {} finally { if (Interlocked.CompareExchange(ref rwlock, RwWrite, state) == state) { writerDoneEvent.Reset(); ctstate.LockState ^= LockState.Write; ++ctstate.WriterRecursiveCount; --numWriteWaiters; registered = false; success = true; } } if (success) { return(true); } } state = rwlock; // We register our interest in taking the Write lock (if upgradeable it's already done) if (!isUpgradable) { while ((state & RwWait) == 0) { try {} finally { if (Interlocked.CompareExchange(ref rwlock, state | RwWait, state) == state) { registered = true; } } if (registered) { break; } state = rwlock; } } // Before falling to sleep do { if (rwlock <= stateCheck) { break; } if ((rwlock & RwWrite) != 0) { writerDoneEvent.Wait(ComputeTimeout(millisecondsTimeout, start)); } else if ((rwlock >> RwReadBit) > 0) { readerDoneEvent.Wait(ComputeTimeout(millisecondsTimeout, start)); } } while (millisecondsTimeout < 0 || (sw.ElapsedMilliseconds - start) < millisecondsTimeout); } while (millisecondsTimeout < 0 || (sw.ElapsedMilliseconds - start) < millisecondsTimeout); --numWriteWaiters; } finally { if (registered) { Interlocked.Add(ref rwlock, isUpgradable ? -RwWaitUpgrade : -RwWait); } } return(false); }
public long AddParticipants(int participantCount) { // check dispose ThrowIfDisposed(); if (participantCount < 1) { throw new ArgumentOutOfRangeException(nameof(participantCount), participantCount, SR.Barrier_AddParticipants_NonPositive_ArgumentOutOfRange); } else if (participantCount > MAX_PARTICIPANTS) //overflow { throw new ArgumentOutOfRangeException(nameof(participantCount), SR.Barrier_AddParticipants_Overflow_ArgumentOutOfRange); } // in case of this is called from the PHA if (_actionCallerID != 0 && Environment.CurrentManagedThreadId == _actionCallerID) { throw new InvalidOperationException(SR.Barrier_InvalidOperation_CalledFromPHA); } SpinWait spinner = default; long newPhase; while (true) { int currentTotal = _currentTotalCount; int total; int current; bool sense; GetCurrentTotal(currentTotal, out current, out total, out sense); if (participantCount + total > MAX_PARTICIPANTS) //overflow { throw new ArgumentOutOfRangeException(nameof(participantCount), SR.Barrier_AddParticipants_Overflow_ArgumentOutOfRange); } if (SetCurrentTotal(currentTotal, current, total + participantCount, sense)) { // Calculating the first phase for that participant, if the current phase already finished return the next phase else return the current phase // To know that the current phase is the sense doesn't match the // phase odd even, so that means it didn't yet change the phase count, so currentPhase +1 is returned, otherwise currentPhase is returned long currPhase = CurrentPhaseNumber; newPhase = (sense != (currPhase % 2 == 0)) ? currPhase + 1 : currPhase; // If this participant is going to join the next phase, which means the postPhaseAction is being running, this participants must wait until this done // and its event is reset. // Without that, if the postPhaseAction takes long time, this means the event that the current participant is going to wait on is still set // (FinishPhase didn't reset it yet) so it should wait until it reset if (newPhase != currPhase) { // Wait on the opposite event if (sense) { _oddEvent.Wait(); } else { _evenEvent.Wait(); } } //This else to fix the racing where the current phase has been finished, m_currentPhase has been updated but the events have not been set/reset yet // otherwise when this participant calls SignalAndWait it will wait on a set event however all other participants have not arrived yet. else { if (sense && _evenEvent.IsSet) { _evenEvent.Reset(); } else if (!sense && _oddEvent.IsSet) { _oddEvent.Reset(); } } break; } spinner.SpinOnce(sleep1Threshold: -1); } return(newPhase); }