/// <summary>Stop tracking a slot.</summary>
            /// <remarks>
            /// Stop tracking a slot.
            /// Must be called with the EndpointShmManager lock held.
            /// </remarks>
            /// <param name="slot">The slot to release.</param>
            internal virtual void FreeSlot(ShortCircuitShm.Slot slot)
            {
                DfsClientShm shm = (DfsClientShm)slot.GetShm();

                shm.UnregisterSlot(slot.GetSlotIdx());
                if (shm.IsDisconnected())
                {
                    // Stale shared memory segments should not be tracked here.
                    Preconditions.CheckState(!this.full.Contains(shm.GetShmId()));
                    Preconditions.CheckState(!this.notFull.Contains(shm.GetShmId()));
                    if (shm.IsEmpty())
                    {
                        if (DfsClientShmManager.Log.IsTraceEnabled())
                        {
                            DfsClientShmManager.Log.Trace(this + ": freeing empty stale " + shm);
                        }
                        shm.Free();
                    }
                }
                else
                {
                    ShortCircuitShm.ShmId shmId = shm.GetShmId();
                    Sharpen.Collections.Remove(this.full, shmId);
                    // The shm can't be full if we just freed a slot.
                    if (shm.IsEmpty())
                    {
                        Sharpen.Collections.Remove(this.notFull, shmId);
                        // If the shared memory segment is now empty, we call shutdown(2) on
                        // the UNIX domain socket associated with it.  The DomainSocketWatcher,
                        // which is watching this socket, will call DfsClientShm#handle,
                        // cleaning up this shared memory segment.
                        //
                        // See #{DfsClientShmManager#domainSocketWatcher} for details about why
                        // we don't want to call DomainSocketWatcher#remove directly here.
                        //
                        // Note that we could experience 'fragmentation' here, where the
                        // DFSClient allocates a bunch of slots in different shared memory
                        // segments, and then frees most of them, but never fully empties out
                        // any segment.  We make some attempt to avoid this fragmentation by
                        // always allocating new slots out of the shared memory segment with the
                        // lowest ID, but it could still occur.  In most workloads,
                        // fragmentation should not be a major concern, since it doesn't impact
                        // peak file descriptor usage or the speed of allocation.
                        if (DfsClientShmManager.Log.IsTraceEnabled())
                        {
                            DfsClientShmManager.Log.Trace(this + ": shutting down UNIX domain socket for " +
                                                          "empty " + shm);
                        }
                        this.Shutdown(shm);
                    }
                    else
                    {
                        this.notFull[shmId] = shm;
                    }
                }
            }
 public virtual void FreeSlot(ShortCircuitShm.Slot slot)
 {
     Lock.Lock();
     try
     {
         DfsClientShm shm = (DfsClientShm)slot.GetShm();
         shm.GetEndpointShmManager().FreeSlot(slot);
     }
     finally
     {
         Lock.Unlock();
     }
 }