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 void Only_one_thread_can_acquire_the_lock_at_a_time() { var l = new Lock<int>(1); var trigger = new ManualResetEvent(false); var first = Async.Fork(() => { trigger.WaitOne(); Thread.Sleep(200); l.Capture(new Result()).Wait(); }, new Result()); Result secondInternal = null; var second = Async.Fork(() => { trigger.WaitOne(); secondInternal = l.Capture(new Result()); }, new Result()); trigger.Set(); Assert.IsFalse(first.HasValue); second.Wait(); l.Release(); Assert.IsTrue(secondInternal.HasValue); Assert.IsFalse(first.HasValue); secondInternal.Wait(); first.Wait(); Assert.IsTrue(first.HasValue); }
public GlobalCacheEntity() { _readCount = 0; _lock = Lock.None; _isDeleted = false; _blockThreads = new Queue<Thread>(); }
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 static LockHolder Hold(Lock l) { LockHolder h; l.Acquire(); h._lock = l; return h; }
public MultiThreadingStressTest(int numberOfThreads) : base("Multi-threading stress test") { if (numberOfThreads < 2) { throw new ArgumentException("numberOfThreads should be greater than 1"); } _threadFinishedLock = new Lock(); _semaphore = new Semaphore(numberOfThreads); _numberOfThreads = numberOfThreads; _failedThreads = 0; }
public GlobalCacheEntity(object value) { Value = value; Version = DateTime.UtcNow.Ticks; _readCount = 0; _lock = Lock.None; _blockThreads = new Queue<Thread>(); ForeignKeys = new Dictionary<string, object>(); ObjectId = Guid.NewGuid(); _isDeleted = false; _writeLockThreadId = -1; _referenceCount = 0; }
public void WhenDone_is_called_when_lock_is_acquired() { var l = new Lock<int>(1); var first = l.Capture(new Result()); var second = l.Capture(new Result()); Assert.IsTrue(first.HasValue); Assert.IsFalse(second.HasValue); var reset = new ManualResetEvent(false); second.WhenDone( _ => reset.Set()); l.Release(); Assert.IsTrue(reset.WaitOne(TimeSpan.FromSeconds(10),true)); Assert.IsTrue(second.HasValue); l.Release(); }
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> /// Helper to ensure the lock object is created before first use. /// </summary> private void EnsureLockObjectCreated() { Contract.Ensures(m_lock != null); Contract.Ensures(m_condition != null); if (m_lock == null) { Lock newObj = new Lock(); Interlocked.CompareExchange(ref m_lock, newObj, null); // failure is benign.. someone else won the race. } if (m_condition == null) { Condition newCond = new Condition(m_lock); Interlocked.CompareExchange(ref m_condition, newCond, null); } }
/// <summary> /// Register initially (eagerly) loaded modules. /// </summary> internal ModuleList() { _loadedModuleMap = new ModuleMap(new ModuleInfo[0]); _moduleRegistrationCallbacks = default(Action<ModuleInfo>); _moduleRegistrationLock = new Lock(); RegisterNewModules(ModuleType.Eager); }
public Condition(Lock @lock) { if (@lock == null) throw new ArgumentNullException("lock"); _lock = @lock; }
private static bool TryAcquireContended(Lock lck, Object obj, int millisecondsTimeout) { #if FEATURE_GET_BLOCKING_OBJECTS int removeCookie = t_blockingObjects.Add(obj, ReasonForBlocking.OnCrst); try { return lck.TryAcquire(millisecondsTimeout); } finally { t_blockingObjects.Remove(removeCookie); } #else return lck.TryAcquire(millisecondsTimeout); #endif }
internal readonly Codec Codec; // for writing new segments /// <summary> /// Constructs a new IndexWriter per the settings given in <code>conf</code>. /// If you want to make "live" changes to this writer instance, use /// <seealso cref="#getConfig()"/>. /// /// <p> /// <b>NOTE:</b> after ths writer is created, the given configuration instance /// cannot be passed to another writer. If you intend to do so, you should /// <seealso cref="IndexWriterConfig#clone() clone"/> it beforehand. /// </summary> /// <param name="d"> /// the index directory. The index is either created or appended /// according <code>conf.getOpenMode()</code>. </param> /// <param name="conf"> /// the configuration settings according to which IndexWriter should /// be initialized. </param> /// <exception cref="IOException"> /// if the directory cannot be read/written to, or if it does not /// exist and <code>conf.getOpenMode()</code> is /// <code>OpenMode.APPEND</code> or if there is any other low-level /// IO error </exception> public IndexWriter(Directory d, IndexWriterConfig conf) { /*if (!InstanceFieldsInitialized) { InitializeInstanceFields(); InstanceFieldsInitialized = true; }*/ readerPool = new ReaderPool(this); conf.SetIndexWriter(this); // prevent reuse by other instances Config_Renamed = new LiveIndexWriterConfig(conf); directory = d; analyzer = Config_Renamed.Analyzer; infoStream = Config_Renamed.InfoStream; mergePolicy = Config_Renamed.MergePolicy; mergePolicy.IndexWriter = this; mergeScheduler = Config_Renamed.MergeScheduler; Codec = Config_Renamed.Codec; BufferedUpdatesStream = new BufferedUpdatesStream(infoStream); PoolReaders = Config_Renamed.ReaderPooling; WriteLock = directory.MakeLock(WRITE_LOCK_NAME); if (!WriteLock.Obtain(Config_Renamed.WriteLockTimeout)) // obtain write lock { throw new LockObtainFailedException("Index locked for write: " + WriteLock); } bool success = false; try { OpenMode_e? mode = Config_Renamed.OpenMode; bool create; if (mode == OpenMode_e.CREATE) { create = true; } else if (mode == OpenMode_e.APPEND) { create = false; } else { // CREATE_OR_APPEND - create only if an index does not exist create = !DirectoryReader.IndexExists(directory); } // If index is too old, reading the segments will throw // IndexFormatTooOldException. segmentInfos = new SegmentInfos(); bool initialIndexExists = true; if (create) { // Try to read first. this is to allow create // against an index that's currently open for // searching. In this case we write the next // segments_N file with no segments: try { segmentInfos.Read(directory); segmentInfos.Clear(); } catch (IOException) { // Likely this means it's a fresh directory initialIndexExists = false; } // Record that we have a change (zero out all // segments) pending: Changed(); } else { segmentInfos.Read(directory); IndexCommit commit = Config_Renamed.IndexCommit; if (commit != null) { // Swap out all segments, but, keep metadata in // SegmentInfos, like version & generation, to // preserve write-once. this is important if // readers are open against the future commit // points. if (commit.Directory != directory) { throw new System.ArgumentException("IndexCommit's directory doesn't match my directory"); } SegmentInfos oldInfos = new SegmentInfos(); oldInfos.Read(directory, commit.SegmentsFileName); segmentInfos.Replace(oldInfos); Changed(); if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "init: loaded commit \"" + commit.SegmentsFileName + "\""); } } } RollbackSegments = segmentInfos.CreateBackupSegmentInfos(); // start with previous field numbers, but new FieldInfos GlobalFieldNumberMap = FieldNumberMap; Config_Renamed.FlushPolicy.Init(Config_Renamed); DocWriter = new DocumentsWriter(this, Config_Renamed, directory); eventQueue = DocWriter.EventQueue(); // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: lock (this) { Deleter = new IndexFileDeleter(directory, Config_Renamed.DelPolicy, segmentInfos, infoStream, this, initialIndexExists); } if (Deleter.StartingCommitDeleted) { // Deletion policy deleted the "head" commit point. // We have to mark ourself as changed so that if we // are closed w/o any further changes we write a new // segments_N file. Changed(); } if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "init: create=" + create); MessageState(); } success = true; } finally { if (!success) { if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "init: hit exception on init; releasing write lock"); } WriteLock.Release(); IOUtils.CloseWhileHandlingException(WriteLock); WriteLock = null; } } }
private void RollbackInternal() { bool success = false; if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "rollback"); } try { lock (this) { FinishMerges(false); StopMerges = true; } if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "rollback: done finish merges"); } // Must pre-close these two, in case they increment // changeCount so that we can then set it to false // before calling closeInternal mergePolicy.Dispose(); mergeScheduler.Dispose(); BufferedUpdatesStream.Clear(); DocWriter.Dispose(); // mark it as closed first to prevent subsequent indexing actions/flushes DocWriter.Abort(this); // don't sync on IW here lock (this) { if (PendingCommit != null) { PendingCommit.RollbackCommit(directory); Deleter.DecRef(PendingCommit); PendingCommit = null; Monitor.PulseAll(this); } // Don't bother saving any changes in our segmentInfos readerPool.DropAll(false); // Keep the same segmentInfos instance but replace all // of its SegmentInfo instances. this is so the next // attempt to commit using this instance of IndexWriter // will always write to a new generation ("write // once"). segmentInfos.RollbackSegmentInfos(RollbackSegments); if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "rollback: infos=" + SegString(segmentInfos.Segments)); } Debug.Assert(TestPoint("rollback before checkpoint")); // Ask deleter to locate unreferenced files & remove // them: Deleter.Checkpoint(segmentInfos, false); Deleter.Refresh(); LastCommitChangeCount = ChangeCount; Deleter.Refresh(); Deleter.Dispose(); WriteLock.Release(); IOUtils.Close(WriteLock); // release write lock WriteLock = null; Debug.Assert(DocWriter.PerThreadPool.NumDeactivatedThreadStates() == DocWriter.PerThreadPool.MaxThreadStates, "" + DocWriter.PerThreadPool.NumDeactivatedThreadStates() + " " + DocWriter.PerThreadPool.MaxThreadStates); } success = true; } catch (System.OutOfMemoryException oom) { HandleOOM(oom, "rollbackInternal"); } finally { if (!success) { // Must not hold IW's lock while closing // mergePolicy/Scheduler: this can lead to deadlock, // e.g. TestIW.testThreadInterruptDeadlock IOUtils.CloseWhileHandlingException(mergePolicy, mergeScheduler); } lock (this) { if (!success) { // we tried to be nice about it: do the minimum // don't leak a segments_N file if there is a pending commit if (PendingCommit != null) { try { PendingCommit.RollbackCommit(directory); Deleter.DecRef(PendingCommit); } catch (Exception) { } } // close all the closeables we can (but important is readerPool and writeLock to prevent leaks) if (WriteLock != null) { WriteLock.Release(); } IOUtils.CloseWhileHandlingException(readerPool, Deleter, WriteLock); WriteLock = null; } closed = true; Closing = false; } } }
public Condition(Lock l) { _lock = l; _waitingList = new NativeArray<TaskHandle>(); }
public void TestLockIdiomUnlocksWhenExceptionsAreThrown() { object sync = new object(); try { lock (sync) { Log("In locked section"); throw new Exception("Purposefully thrown"); } } catch (Exception) { } bool secondThreadAcquiredLock = false; Lock secondThreadDoneLock = new Lock(); Condition secondThreadDone = new Condition(secondThreadDoneLock); Thread secondThread = new Thread(delegate() { secondThreadAcquiredLock = Monitor.TryEnter(sync); }); secondThread.Start(); secondThreadDone.Await(); Assert("Finally block of lock idiom should have unlocked sync obj", secondThreadAcquiredLock); }
private static bool TryAcquireContended(Lock lck, Object obj, int millisecondsTimeout) { int removeCookie = t_blockingObjects.Add(obj, ReasonForBlocking.OnCrst); try { return lck.TryAcquire(millisecondsTimeout); } finally { t_blockingObjects.Remove(removeCookie); } }
/// <summary> /// Register initially (eagerly) loaded modules. /// </summary> internal ModuleList() { _loadedModuleMap = new ModuleMap(new ModuleInfo[0]); _moduleRegistrationCallbacks = default(Action<ModuleInfo>); _moduleRegistrationLock = new Lock(); // Fetch modules that have already been registered with the runtime int loadedModuleCount = RuntimeAugments.GetLoadedModules(null); IntPtr[] loadedModuleHandles = new IntPtr[loadedModuleCount]; int loadedModuleCountUpdated = RuntimeAugments.GetLoadedModules(loadedModuleHandles); Debug.Assert(loadedModuleCount == loadedModuleCountUpdated); foreach (IntPtr moduleHandle in loadedModuleHandles) { RegisterModule(moduleHandle); } }
/// <summary> /// Register initially (eagerly) loaded modules. /// </summary> internal ModuleList() { _loadedModuleMap = new ModuleMap(new ModuleInfo[0]); _moduleRegistrationCallbacks = default(Action<ModuleInfo>); _moduleRegistrationLock = new Lock(); RegisterNewModules(ModuleType.Eager); IntPtr systemObjectModule = RuntimeAugments.GetModuleFromTypeHandle(RuntimeAugments.RuntimeTypeHandleOf<object>()); foreach (ModuleInfo m in _loadedModuleMap.Modules) { if (m.Handle == systemObjectModule) { _systemModule = m; break; } } }
private void CloseInternal(bool waitForMerges, bool doFlush) { bool interrupted = false; try { if (PendingCommit != null) { throw new InvalidOperationException("cannot close: prepareCommit was already called with no corresponding call to commit"); } if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "now flush at close waitForMerges=" + waitForMerges); } DocWriter.Dispose(); try { // Only allow a new merge to be triggered if we are // going to wait for merges: if (doFlush) { Flush(waitForMerges, true); } else { DocWriter.Abort(this); // already closed -- never sync on IW } } finally { try { // clean up merge scheduler in all cases, although flushing may have failed: //interrupted = Thread.Interrupted(); //LUCENE TO-DO interrupted = false; if (waitForMerges) { try { // Give merge scheduler last chance to run, in case // any pending merges are waiting: mergeScheduler.Merge(this, MergeTrigger.CLOSING, false); } catch (ThreadInterruptedException) { // ignore any interruption, does not matter interrupted = true; if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "interrupted while waiting for final merges"); } } } lock (this) { for (; ; ) { try { FinishMerges(waitForMerges && !interrupted); break; } catch (ThreadInterruptedException) { // by setting the interrupted status, the // next call to finishMerges will pass false, // so it will not wait interrupted = true; if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "interrupted while waiting for merges to finish"); } } } StopMerges = true; } } finally { // shutdown policy, scheduler and all threads (this call is not interruptible): IOUtils.CloseWhileHandlingException(mergePolicy, mergeScheduler); } } if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "now call final commit()"); } if (doFlush) { CommitInternal(); } ProcessEvents(false, true); lock (this) { // commitInternal calls ReaderPool.commit, which // writes any pending liveDocs from ReaderPool, so // it's safe to drop all readers now: readerPool.DropAll(true); Deleter.Dispose(); } if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "at close: " + SegString()); } if (WriteLock != null) { WriteLock.Release(); // release write lock WriteLock.Dispose(); WriteLock = null; } lock (this) { closed = true; } Debug.Assert(DocWriter.PerThreadPool.NumDeactivatedThreadStates() == DocWriter.PerThreadPool.MaxThreadStates, "" + DocWriter.PerThreadPool.NumDeactivatedThreadStates() + " " + DocWriter.PerThreadPool.MaxThreadStates); } catch (System.OutOfMemoryException oom) { HandleOOM(oom, "closeInternal"); } finally { lock (this) { Closing = false; Monitor.PulseAll(this); if (!closed) { if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "hit exception while closing"); } } } // finally, restore interrupt status: if (interrupted) { Thread.CurrentThread.Interrupt(); } } }
/// <summary> /// Assigns a sync table entry to the object in a thread-safe way. /// </summary> public static unsafe int AssignEntry(object obj, int* pHeader) { // Allocate the synchronization object outside the lock Lock lck = new Lock(); using (LockHolder.Hold(s_freeEntriesLock)) { // After acquiring the lock check whether another thread already assigned the sync entry int hashOrIndex; if (ObjectHeader.GetSyncEntryIndex(*pHeader, out hashOrIndex)) { return hashOrIndex; } // Allocate a new sync entry. First, make sure all data is ready. This call may OOM. GCHandle owner = GCHandle.Alloc(obj, GCHandleType.WeakTrackResurrection); try { // Now find a free entry in the table int syncIndex; if (s_freeEntryList != 0) { // Grab a free entry from the list syncIndex = s_freeEntryList; s_freeEntryList = s_entries[syncIndex].Next; s_entries[syncIndex].Next = 0; } else if (s_unusedEntryIndex < s_entries.Length) { // Grab the next unused entry syncIndex = s_unusedEntryIndex++; } else { // No free entries, use the slow path. This call may OOM. syncIndex = EnsureFreeEntry(); } // Found a free entry to assign Debug.Assert(!s_entries[syncIndex].Owner.IsAllocated); Debug.Assert(s_entries[syncIndex].Lock == null); Debug.Assert(s_entries[syncIndex].HashCode == 0); // Set up the new entry. We should not fail after this point. s_entries[syncIndex].Lock = lck; // The hash code will be set by the SetSyncEntryIndex call below s_entries[syncIndex].Owner = owner; owner = default(GCHandle); // Finally, store the entry index in the object header ObjectHeader.SetSyncEntryIndex(pHeader, syncIndex); return syncIndex; } finally { if (owner.IsAllocated) { owner.Free(); } } } }
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; }