/// <summary> /// Simple helper method to set the acquired state and time acquired of a MutexInfo. /// </summary> /// <param name="info">The MutexInfo to set the status of</param> /// <param name="isAcquired">True if the mutex is owned; false otherwise.</param> private void SetOwned(MutexInfo info, bool isAcquired) { info.Attached = isAcquired; if (isAcquired) { info.TimeAcquired = DateTime.Now; } _ownedMutexes[info.Name] = info; }
/// <summary> /// Releases the specified mutex, if owned. /// </summary> /// <param name="name">The name of the mutex to release</param> public void ReleaseMutex(string name) { if (!OwnsMutex(name)) { return; } MutexInfo mutex = _ownedMutexes[name]; this.MemcachedClient.Cas(this.KeyPrefix + mutex.Name, null, mutex.CasToken, 1); this.SetOwned(mutex, false); }
/// <summary> /// Acquires a mutex. /// </summary> /// <param name="name">The name of the mutex to acquire</param> /// <param name="msTimeout">The milliseconds to wait before giving up on acquiring</param> /// <param name="msLifetime">The maximum length of time the mutex will last after being acquired; -1 for infinity.</param> /// <returns>True on success, false on failure.</returns> public bool AcquireMutex(string name, long msTimeout, long msLifetime) { if (msLifetime < -1 || msLifetime == 0) { throw new ArgumentOutOfRangeException("msLifetime", "msLifetime must be either -1 or a positive integer."); } if (OwnsMutex(name)) { return(true); } long memcachedLifetime = (msLifetime == -1) ? 0 : msLifetime; //Memcached requires a lifetime of 0 for infinite-length mutexes MutexInfo mutex; if (!_ownedMutexes.ContainsKey(name)) { mutex = new MutexInfo() { Name = name, Lifetime = msLifetime, ServerGUID = this.GUID, }; } else { mutex = _ownedMutexes[name]; mutex.Lifetime = msLifetime; } DateTime beganAcquiring = DateTime.Now; string memcachedKey = this.KeyPrefix + name; ulong casToken = 0; while (((DateTime.Now - beganAcquiring).TotalMilliseconds < msTimeout) || msTimeout == -1) { object currentOwnerRaw = this.MemcachedClient.Get(memcachedKey, ref casToken); if (currentOwnerRaw == null) { bool setOwner = casToken == 0 ? this.MemcachedClient.Add(memcachedKey, this.GUID, memcachedLifetime) : this.MemcachedClient.Cas(memcachedKey, this.GUID, casToken, memcachedLifetime); if (setOwner) { ulong newCasToken = 0; string newOwner = (string)this.MemcachedClient.Get(memcachedKey, ref newCasToken); if (newOwner == this.GUID) { mutex.CasToken = newCasToken; this.SetOwned(mutex, true); } } } else { string currentOwner = (string)currentOwnerRaw; if (currentOwner == this.GUID) { this.SetOwned(mutex, true); return(true); } } Thread.Sleep(this.SleepTime); } this.SetOwned(mutex, false); return(false); }