public override ThreadState GetAndLock(Thread requestingThread, DocumentsWriter documentsWriter) { ThreadState threadState = null; if (NumThreadStatesActive == 0) { lock (this) { if (NumThreadStatesActive == 0) { threadState = states[0] = NewThreadState(); return(threadState); } } } Debug.Assert(NumThreadStatesActive > 0); for (int i = 0; i < maxRetry; i++) { int ord = random.Next(NumThreadStatesActive); lock (this) { threadState = states[ord]; Debug.Assert(threadState != null); } if (threadState.TryLock()) { return(threadState); } if (random.Next(20) == 0) { break; } } /* * only try to create a new threadstate if we can not lock the randomly * selected state. this is important since some tests rely on a single * threadstate in the single threaded case. Eventually it would be nice if * we would not have this limitation but for now we just make sure we only * allocate one threadstate if indexing is single threaded */ lock (this) { ThreadState newThreadState = NewThreadState(); if (newThreadState != null) // did we get a new state? { threadState = states[NumThreadStatesActive - 1] = newThreadState; //Debug.Assert(threadState.HeldByCurrentThread); return(threadState); } // if no new state is available lock the random one } Debug.Assert(threadState != null); threadState.@Lock(); return(threadState); }
internal DocumentsWriterPerThread NextPendingFlush() { int numPending; bool fullFlush; UninterruptableMonitor.Enter(this); try { DocumentsWriterPerThread poll; if (flushQueue.Count > 0 && (poll = flushQueue.Dequeue()) != null) { UpdateStallState(); return(poll); } fullFlush = this.fullFlush; numPending = this.numPending; } finally { UninterruptableMonitor.Exit(this); } if (numPending > 0 && !fullFlush) // don't check if we are doing a full flush { int limit = perThreadPool.NumThreadStatesActive; for (int i = 0; i < limit && numPending > 0; i++) { ThreadState next = perThreadPool.GetThreadState(i); if (next.flushPending && next.TryLock()) // LUCENENET specific: Since .NET Core 2+ uses fair locking, we need to ensure we have a lock before calling InternalTryCheckoutForFlush. See # { try { DocumentsWriterPerThread dwpt = TryCheckoutForFlush(next); if (dwpt != null) { return(dwpt); } } finally { next.Unlock(); } } } } return(null); }
private DocumentsWriterPerThread InternalTryCheckOutForFlush(ThreadState perThread) { //Debug.Assert(Thread.HoldsLock(this)); Debug.Assert(perThread.flushPending); try { // We are pending so all memory is already moved to flushBytes if (perThread.TryLock()) { try { if (perThread.IsInitialized) { //Debug.Assert(perThread.HeldByCurrentThread); DocumentsWriterPerThread dwpt; long bytes = perThread.bytesUsed; // do that before // replace! dwpt = perThreadPool.Reset(perThread, closed); Debug.Assert(!flushingWriters.ContainsKey(dwpt), "DWPT is already flushing"); // Record the flushing DWPT to reduce flushBytes in doAfterFlush flushingWriters[dwpt] = Convert.ToInt64(bytes); numPending--; // write access synced return(dwpt); } } finally { perThread.Unlock(); } } return(null); } finally { UpdateStallState(); } }