Ejemplo n.º 1
0
        /// <summary>
        /// Check the thread with the current turn for the lock and grant a secondary lock if applicable.
        /// </summary>
        /// <param name="candidateLock">An unexpired lock request on the current thread, or null to just check the turn thread.</param>
        /// <returns>The Thread with the current turn for the lock, or null if there are none holding or waiting.</returns>
        internal Thread CheckCurrentTurnThread(InterprocessLock candidateLock)
        {
            if (candidateLock != null && candidateLock.OwningThread != Thread.CurrentThread)
            {
                throw new InvalidOperationException("A lock request may only be waited on by the thread which created it.");
            }

            lock (m_QueueLock)
            {
                if (m_CurrentLockTurn != null)
                {
                    Thread currentOwningThread = m_CurrentLockTurn.OwningThread;
                    if (candidateLock != null && Thread.CurrentThread == currentOwningThread)
                    {
                        candidateLock.GrantTheLock(m_CurrentLockTurn);     // Set it as a secondary lock on that holder (same thread).
                        if (candidateLock.ActualLock == m_CurrentLockTurn) // Sanity-check that it was successful.
                        {
                            candidateLock.OurLockProxy = this;             // So its dispose-on-close setting pass-through can function.
                        }
                    }

                    return(currentOwningThread); // Whether it's a match or some other thread.
                }

                return(null); // No thread owns the lock.
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Wait for our turn to have the lock (and wait for the lock) up to our time limit
        /// </summary>
        /// <param name="lockRequest"></param>
        /// <returns></returns>
        internal bool AwaitOurTurnOrTimeout(InterprocessLock lockRequest)
        {
            if (lockRequest.IsExpired)
            {
                throw new InvalidOperationException("Can't wait on an expired lock request.");
            }

            if (string.Equals(lockRequest.FullName, m_LockFullFileNamePath, StringComparison.OrdinalIgnoreCase) == false)
            {
                throw new InvalidOperationException("A lock request may not be queued to a proxy for a different full name.");
            }

            if (lockRequest.OwningThread != Thread.CurrentThread)
            {
                throw new InvalidOperationException("A lock request may only be waited on by the thread which created it.");
            }

            lockRequest.OurLockProxy = this; // Mark the request as pending with us.

            // Do NOT clear out current lock owner, this will allow DequeueNextRequest to find one already there, if any.
            bool ourTurn = StartNextTurn(lockRequest); // Gets its own queue lock.

            if (ourTurn == false)
            {
                // It's not our turn yet, we need to wait our turn.  Are we willing to wait?
                if (lockRequest.WaitForLock && lockRequest.WaitTimeout > DateTimeOffset.Now)
                {
                    ourTurn = lockRequest.AwaitTurnOrTimeout();
                }

                // Still not our turn?
                if (ourTurn == false)
                {
                    if (!CommonCentralLogic.SilentMode)
                    {
                        // Who actually has the lock right now?
                        if (m_CurrentLockTurn != null)
                        {
                            Thread currentOwningThread     = m_CurrentLockTurn.OwningThread;
                            int    currentOwningThreadId   = -1;
                            string currentOwningThreadName = "null";
                            if (currentOwningThread != null) // To make sure we can't get a null-ref exception from logging this...
                            {
                                currentOwningThreadId   = currentOwningThread.ManagedThreadId;
                                currentOwningThreadName = currentOwningThread.Name ?? string.Empty;
                            }

                            m_Logger.LogDebug("{0}\r\nA lock request gave up because it is still being held by another thread.\r\n" +
                                              "Lock file: {1}\r\nCurrent holding thread: {2} ({3})",
                                              lockRequest.WaitForLock ? "Lock request timed out" : "Lock request couldn't wait",
                                              m_LockFullFileNamePath, currentOwningThreadId, currentOwningThreadName);
                        }
                        else
                        {
                            m_Logger.LogError("Lock request turn error\r\nA lock request failed to get its turn but the current lock turn is null.  " +
                                              "This probably should not happen.\r\nLock file: {0}\r\n", m_LockFullFileNamePath);
                        }
                    }

                    lockRequest.Dispose(); // Expire the request.
                    return(false);         // Failed to get the lock.  Time to give up.
                }
            }

            // Yay, now it's our turn!  Do we already hold the lock?

            bool validLock;

            if (m_FileLock != null)
            {
                validLock = true; // It's our request's turn and this proxy already holds the lock!
            }
            else
            {
                validLock = TryGetLock(lockRequest); // Can we get the lock?
            }
            // Do we actually have the lock now?
            if (validLock)
            {
                lockRequest.GrantTheLock(lockRequest); // It owns the actual lock itself now.
            }
            else
            {
                if (!CommonCentralLogic.SilentMode)
                {
                    m_Logger.LogTrace("{0}\r\nA lock request gave up because it could not obtain the file lock.  " +
                                      "It is most likely still held by another process.\r\nLock file: {1}",
                                      lockRequest.WaitForLock ? "Lock request timed out" : "Lock request couldn't wait",
                                      m_LockFullFileNamePath);
                }

                lockRequest.Dispose(); // Failed to get the lock.  Expire the request and give up.
            }

            return(validLock);
        }