This is a cross-platform, global, named mutex that can be used to synchronize access to data across processes. It supports reentrant locking. This is needed because Mono does not support system-wide, named mutexes. Mono does implement the Mutex class, but even when using the constructors with names, it only works within a single process.
Inheritance: SIL.Utils.FwDisposableBase
Esempio n. 1
0
		public void Initialize_CreatedNew_ReturnsTrue()
		{
			using (var mutex = new GlobalMutex("test"))
			{
				mutex.Unlink();
				Assert.That(mutex.Initialize(), Is.True);
				mutex.Unlink();
			}
		}
Esempio n. 2
0
 public void Initialize_CreatedNew_ReturnsTrue()
 {
     using (var mutex = new GlobalMutex("test"))
     {
         mutex.Unlink();
         Assert.That(mutex.Initialize(), Is.True);
         mutex.Unlink();
     }
 }
Esempio n. 3
0
		public void Initialize_Existing_ReturnsFalse()
		{
			using (var mutex1 = new GlobalMutex("test"))
			{
				mutex1.Initialize();
				using (var mutex2 = new GlobalMutex("test"))
					Assert.That(mutex2.Initialize(), Is.False);
				mutex1.Unlink();
			}
		}
Esempio n. 4
0
 public void Initialize_Existing_ReturnsFalse()
 {
     using (var mutex1 = new GlobalMutex("test"))
     {
         mutex1.Initialize();
         using (var mutex2 = new GlobalMutex("test"))
             Assert.That(mutex2.Initialize(), Is.False);
         mutex1.Unlink();
     }
 }
Esempio n. 5
0
		public void InitializeAndLock_Reentrancy_DoesNotBlock()
		{
			using (var mutex = new GlobalMutex("test"))
			{
				using (mutex.InitializeAndLock())
				{
					using (mutex.Lock()) {}
				}
				mutex.Unlink();
			}
		}
Esempio n. 6
0
		public void InitializeAndLock_CreatedNew_ReturnsTrue()
		{
			using (var mutex = new GlobalMutex("test"))
			{
				mutex.Unlink();
				bool createdNew;
				using (mutex.InitializeAndLock(out createdNew)) {}
				Assert.That(createdNew, Is.True);
				mutex.Unlink();
			}
		}
Esempio n. 7
0
 public void InitializeAndLock_Reentrancy_DoesNotBlock()
 {
     using (var mutex = new GlobalMutex("test"))
     {
         using (mutex.InitializeAndLock())
         {
             using (mutex.Lock()) {}
         }
         mutex.Unlink();
     }
 }
Esempio n. 8
0
 public void InitializeAndLock_CreatedNew_ReturnsTrue()
 {
     using (var mutex = new GlobalMutex("test"))
     {
         mutex.Unlink();
         bool createdNew;
         using (mutex.InitializeAndLock(out createdNew)) {}
         Assert.That(createdNew, Is.True);
         mutex.Unlink();
     }
 }
Esempio n. 9
0
		public void InitializeAndLock_Existing_ReturnsFalse()
		{
			using (var mutex1 = new GlobalMutex("test"))
			{
				mutex1.Initialize();
				using (var mutex2 = new GlobalMutex("test"))
				{
					bool createdNew;
					using (mutex2.InitializeAndLock(out createdNew)) {}
					Assert.That(createdNew, Is.False);
				}
				mutex1.Unlink();
			}
		}
Esempio n. 10
0
 public void InitializeAndLock_Existing_ReturnsFalse()
 {
     using (var mutex1 = new GlobalMutex("test"))
     {
         mutex1.Initialize();
         using (var mutex2 = new GlobalMutex("test"))
         {
             bool createdNew;
             using (mutex2.InitializeAndLock(out createdNew)) {}
             Assert.That(createdNew, Is.False);
         }
         mutex1.Unlink();
     }
 }
		protected override int StartupInternal(int currentModelVersion)
		{
			m_commitLogMutex = new GlobalMutex(MutexName);
			bool createdNew;
			using (m_commitLogMutex.InitializeAndLock(out createdNew))
			{
				CreateSharedMemory(createdNew);
				using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream())
				{
					CommitLogMetadata metadata = null;
					if (!createdNew)
					{
						if (TryGetMetadata(stream, out metadata))
						{
							CheckExitedPeerProcesses(metadata);
							if (m_peerProcesses.Count == 0)
								createdNew = true;
						}
						else
						{
							createdNew = true;
						}
					}

					if (createdNew)
						metadata = new CommitLogMetadata();

					using (Process curProcess = Process.GetCurrentProcess())
						metadata.Peers[m_peerID] = new CommitLogPeer { ProcessID = curProcess.Id, Generation = metadata.FileGeneration };

					if (metadata.Master == Guid.Empty)
					{
						base.LockProject();
						metadata.Master = m_peerID;
					}

					int startupModelVersion = ReadInSurrogates(currentModelVersion);
					// non-master peers cannot migrate the XML file
					if (startupModelVersion < currentModelVersion && metadata.Master != m_peerID)
						throw new FdoDataMigrationForbiddenException();

					SaveMetadata(stream, metadata);

					return startupModelVersion;
				}
			}
		}
		protected override void CreateInternal()
		{
			m_commitLogMutex = new GlobalMutex(MutexName);

			using (m_commitLogMutex.InitializeAndLock())
			{
				CreateSharedMemory(true);
				var metadata = new CommitLogMetadata { Master = m_peerID };
				using (Process curProcess = Process.GetCurrentProcess())
					metadata.Peers[m_peerID] = new CommitLogPeer { ProcessID = curProcess.Id, Generation = metadata.FileGeneration };
				using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream())
				{
					SaveMetadata(stream, metadata);
				}

				base.CreateInternal();
			}
		}
		protected override void ShutdownInternal()
		{
			if (m_commitLogMutex != null && m_commitLogMetadata != null)
			{
				CompleteAllCommits();
				using (m_commitLogMutex.Lock())
				{
#if __MonoCS__
					bool delete = false;
#endif
					using (MemoryMappedViewStream stream = m_commitLogMetadata.CreateViewStream())
					{
						CommitLogMetadata metadata;
						if (TryGetMetadata(stream, out metadata))
						{
							if (metadata.Master == m_peerID)
							{
								// commit any unseen foreign changes
								List<ICmObjectSurrogate> foreignNewbies;
								List<ICmObjectSurrogate> foreignDirtballs;
								List<ICmObjectId> foreignGoners;
								if (GetUnseenForeignChanges(metadata, out foreignNewbies, out foreignDirtballs, out foreignGoners))
								{
									var newObjects = new HashSet<ICmObjectOrSurrogate>(foreignNewbies);
									var editedObjects = new HashSet<ICmObjectOrSurrogate>(foreignDirtballs);
									var removedObjects = new HashSet<ICmObjectId>(foreignGoners);

									IEnumerable<CustomFieldInfo> fields;
									if (HaveAnythingToCommit(newObjects, editedObjects, removedObjects, out fields) && (StartupVersionNumber == ModelVersion))
										base.WriteCommitWork(new CommitWork(newObjects, editedObjects, removedObjects, fields));
								}
								// XML file is now totally up-to-date
								metadata.FileGeneration = metadata.CurrentGeneration;
							}
							RemovePeer(metadata, m_peerID);
#if __MonoCS__
							delete = metadata.Peers.Count == 0;
#endif
							SaveMetadata(stream, metadata);
						}
					}

					base.UnlockProject();

					m_commitLog.Dispose();
					m_commitLog = null;

					m_commitLogMetadata.Dispose();
					m_commitLogMetadata = null;

#if __MonoCS__
					if (delete)
					{
						File.Delete(Path.Combine(m_commitLogDir, CommitLogMetadataName));
						File.Delete(Path.Combine(m_commitLogDir, CommitLogName));
						m_commitLogMutex.Unlink();
					}
#endif
				}
			}

			if (m_commitLogMutex != null)
			{
				m_commitLogMutex.Dispose();
				m_commitLogMutex = null;
			}

			if (CommitThread != null)
			{
				CommitThread.Stop();
				CommitThread.Dispose();
				CommitThread = null;
			}

			foreach (Process peerProcess in m_peerProcesses.Values)
				peerProcess.Close();
			m_peerProcesses.Clear();
		}