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);
        }
Example #3
0
 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();
     }
 }