public override void PerformTest() { Log("Creating " + _numberOfThreads + " threads"); Thread[] threads = new Thread[_numberOfThreads]; for (int i = 0; i < _numberOfThreads; i++) { threads[i] = new Thread(Work, ThreadPriority.Normal); } _startedThreads = 0; _startedThreadsLock = new Lock(); _allThreadsStartedLock = new Lock(); _allThreadsStartedCondition = new Condition(_allThreadsStartedLock); _allThreadsStartedLock.Acquire(); Log("Starting " + _numberOfThreads + " threads"); // TODO: ParametizedThreadStart doesn't work properly for (int i = 0; i < _numberOfThreads; i++) { threads[i].Start(); } // wait for all threads to be running _allThreadsStartedCondition.Await(); _allThreadsStartedLock.Release(); Log("Waiting for all threads to finish"); _semaphore.Acquire(_numberOfThreads); // wait for all threads to finish Assert(_failedThreads + " threads failed the calculation", _failedThreads == 0); Log("All " + _numberOfThreads + " threads finished"); }
public void TestAbortThread() { Lock sync = new Lock(); TimedCondition aborted = new TimedCondition(sync); Thread testThread = new Thread(delegate() { try { Log("Test thread sleeping for 8 seconds.."); Thread.Sleep(8000); } catch (ThreadAbortException) { Log("Test thread aborted.."); aborted.Signal(); } Fail("This line should never be executed"); }); testThread.Start(); sync.Acquire(); Log("Aborting test thread in 2 seconds. Sleeping..."); Thread.Sleep(2000); Log("...awake! Going to abort the test thread."); testThread.Abort(); Log("Called testThread.Abort()"); try { aborted.Await(12000); } catch (ConditionTimedOutException) { Fail("Thread was not aborted as expected!"); } }
public static LockHolder Hold(Lock l) { LockHolder h; l.Acquire(); h._lock = l; return h; }
public static LockHolder Hold(Lock l) { LockHolder h; l.Acquire(); h._lock = l; return(h); }
public override void PerformTest() { _mainLock = new Lock(); Thread controllerThread = new Thread(ControllerThreadStart, ThreadPriority.Normal); controllerThread.Name = "Controller Thread"; controllerThread.Start(); Thread.Sleep(2000); Log("Main thread is trying to acquire the main lock..."); _mainLock.Acquire(); Log("Main thread got the main lock..."); }
public object Call(string method, object[] args, int timeout) { XmlHttpRequest xhr = XmlHttpRequestManager.GetXmlHttpRequest(); Lock l = new Lock(); l.Acquire(); TimedCondition condition = new TimedCondition(l); OnReadyStateChangeHandler handler = new OnReadyStateChangeHandler(xhr, condition); xhr.OnReadyStateChange = (NativeFunction)new VoidDelegate(handler.OnReadyStateChange); xhr.Open("POST", ServerUrl, true, Username, Password); xhr.SetRequestHeader(RpcMethodRequestHeader, method); xhr.Send(Serialize(args)); if (timeout > 0) { try { // wait for timeout milliseconds condition.Await(timeout); } catch (ConditionTimedOutException) { Logging.Debug("Request timed out!!!"); throw new JsonRpcCallTimedOutException(this, method, args, timeout); } } else { // wait indefinitely condition.Await(); } // we have a response from the server, or we couldn't connect Logging.Debug("Status code is: " + xhr.Status); if (xhr.Status == 200) { Logging.Debug("Got 200! Response text is " + xhr.ResponseText); return Deserialize(xhr.ResponseText); } else if (xhr.Status == 0) { Logging.Debug("Request timed out!!!"); throw new JsonRpcCallTimedOutException(this, method, args, 1000); // TODO: Extract into constant of 1000 ms. Also this should be some sort of connection refused exception instead } else { throw GenerateException(xhr.Status, method, args, xhr.ResponseText); } }
public void TestAbortThreadWithState() { Lock sync = new Lock(); TimedCondition aborted = new TimedCondition(sync); Thread testThread = new Thread(delegate() { try { Log("Test thread sleeping for 8 seconds.."); Thread.Sleep(8000); } catch (ThreadAbortException e) { if (e.ExceptionState != null && e.ExceptionState.ToString() == "Exception state") { Log("Test thread aborted with state: " + e.ExceptionState); aborted.Signal(); } else { Log("Test thread aborted with unknown state: " + e.ExceptionState); } } Fail("This line should never be executed"); }); testThread.Start(); sync.Acquire(); Log("Aborting test thread in 2 seconds"); Thread.Sleep(2000); testThread.Abort("Exception state"); try { aborted.Await(12000); } catch (ConditionTimedOutException) { Fail("Thread was not aborted as expected!"); } }
/// <summary> /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>, /// using a 32-bit signed integer to measure the time interval, /// while observing a <see cref="T:System.Threading.CancellationToken"/>. /// </summary> /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to /// wait indefinitely.</param> /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to observe.</param> /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>; otherwise, false.</returns> /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a negative number other than -1, /// which represents an infinite time-out.</exception> /// <exception cref="System.OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception> public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) { CheckDispose(); // Validate input if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException( "totalMilliSeconds", millisecondsTimeout, SR.SemaphoreSlim_Wait_TimeoutWrong); } cancellationToken.ThrowIfCancellationRequested(); uint startTime = 0; if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0) { startTime = TimeoutHelper.GetTime(); } bool waitSuccessful = false; Task <bool> asyncWaitTask = null; bool lockTaken = false; //Register for cancellation outside of the main lock. //NOTE: Register/deregister inside the lock can deadlock as different lock acquisition orders could // occur for (1)this.m_lockObj and (2)cts.internalLock CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCanceledEventHandler, this); try { // Perf: first spin wait for the count to be positive, but only up to the first planned yield. // This additional amount of spinwaiting in addition // to Monitor.Enter()’s spinwaiting has shown measurable perf gains in test scenarios. // SpinWait spin = new SpinWait(); while (m_currentCount == 0 && !spin.NextSpinWillYield) { spin.SpinOnce(); } // entering the lock and incrementing waiters must not suffer a thread-abort, else we cannot // clean up m_waitCount correctly, which may lead to deadlock due to non-woken waiters. try { } finally { m_lock.Acquire(); lockTaken = true; if (lockTaken) { m_waitCount++; } } // If there are any async waiters, for fairness we'll get in line behind // then by translating our synchronous wait into an asynchronous one that we // then block on (once we've released the lock). if (m_asyncHead != null) { Debug.Assert(m_asyncTail != null, "tail should not be null if head isn't"); asyncWaitTask = WaitAsync(millisecondsTimeout, cancellationToken); } // There are no async waiters, so we can proceed with normal synchronous waiting. else { // If the count > 0 we are good to move on. // If not, then wait if we were given allowed some wait duration OperationCanceledException oce = null; if (m_currentCount == 0) { if (millisecondsTimeout == 0) { return(false); } // Prepare for the main wait... // wait until the count become greater than zero or the timeout is expired try { waitSuccessful = WaitUntilCountOrTimeout(millisecondsTimeout, startTime, cancellationToken); } catch (OperationCanceledException e) { oce = e; } } // Now try to acquire. We prioritize acquisition over cancellation/timeout so that we don't // lose any counts when there are asynchronous waiters in the mix. Asynchronous waiters // defer to synchronous waiters in priority, which means that if it's possible an asynchronous // waiter didn't get released because a synchronous waiter was present, we need to ensure // that synchronous waiter succeeds so that they have a chance to release. Debug.Assert(!waitSuccessful || m_currentCount > 0, "If the wait was successful, there should be count available."); if (m_currentCount > 0) { waitSuccessful = true; m_currentCount--; } else if (oce != null) { throw oce; } // Exposing wait handle which is lazily initialized if needed if (m_waitHandle != null && m_currentCount == 0) { m_waitHandle.Reset(); } } } finally { // Release the lock if (lockTaken) { m_waitCount--; m_lock.Release(); } // Unregister the cancellation callback. cancellationTokenRegistration.Dispose(); } // If we had to fall back to asynchronous waiting, block on it // here now that we've released the lock, and return its // result when available. Otherwise, this was a synchronous // wait, and whether we successfully acquired the semaphore is // stored in waitSuccessful. return((asyncWaitTask != null) ? asyncWaitTask.GetAwaiter().GetResult() : waitSuccessful); }
private static XmlHttpRequest _doSimpleXmlHttpRequest(string url, RequestMethod method, string postData, string username, string password, int timeoutMs) { XmlHttpRequest xhr = GetXmlHttpRequest(); Lock l = new Lock(); l.Acquire(); Condition condition = new Condition(l); if (_driverProcess == null) { throw new SystemException("XmlHttpRequestManager.Driver was not started."); } OnReadyStateChangeSignalHandler handler = new OnReadyStateChangeSignalHandler { XmlHttpRequest = xhr, Condition = condition }; // TODO: Use resource manager to ensure these signal senders and handlers get cleaned up OnReadyStateChangeSignalSender signalSender = CreateOnReadyStateChangeSignalSender(handler); try { xhr.OnReadyStateChange = (NativeFunction)new NativeVoidDelegate(signalSender.SendSignal); string methodString; if (method == RequestMethod.Get) { methodString = "GET"; } else { methodString = "POST"; } xhr.Open(methodString, url, true, username, password); xhr.Send(postData); if (timeoutMs > 0) { if (!condition.Await(timeoutMs)) { xhr.OnReadyStateChange = null; throw new XmlHttpRequestTimeoutException("Timed out waiting for " + url, xhr); } } else { condition.Await(); } // TODO: finally blocks are not executed if there is a return statement in the try block. fix that } finally { DestroyOnReadyStateChangeSignalSender(signalSender); } return xhr; }