Ejemplo n.º 1
0
 /// <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;
 }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 3
0
        /// <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);
        }