// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; using EpicGames.Core; using UnrealBuildBase; namespace UnrealBuildTool { /// /// System-wide mutex allowing only one instance of the program to run at a time /// class SingleInstanceMutex : IDisposable { /// /// The global mutex instance /// Mutex? GlobalMutex; /// /// Constructor. Attempts to acquire the global mutex /// /// Name of the mutex to acquire /// public SingleInstanceMutex(string MutexName, bool bWaitMutex) { // Try to create the mutex, with it initially locked bool bCreatedMutex; GlobalMutex = new Mutex(true, MutexName, out bCreatedMutex); // If we didn't create the mutex, we can wait for it or fail immediately if (!bCreatedMutex) { if (bWaitMutex) { try { GlobalMutex.WaitOne(); } catch (AbandonedMutexException) { } } else { throw new BuildException("A conflicting instance of UnrealBuildTool is already running."); } } } /// /// Gets the name of a mutex unique for the given path /// /// Base name of the mutex /// Path to identify a unique mutex public static string GetUniqueMutexForPath(string Name, string UniquePath) { // generate a md5 hash of the path, as GetHashCode is not guaranteed to generate a stable hash return string.Format("Global\\{0}_{1}", Name, ContentHash.MD5(UniquePath.ToUpperInvariant())); } /// /// Release the mutex and dispose of the object /// public void Dispose() { if (GlobalMutex != null) { GlobalMutex.ReleaseMutex(); GlobalMutex.Dispose(); GlobalMutex = null; } } } }