internal void DisconnectInternal(bool sendMessage, bool timeout) { #if ALLOW_CONNECTION_STUB if (IsStub) { // NOOP return; } #endif // TODO: Could be just a normal write lock. The chance of it not being a write in the end is small. _stateLock.EnterUpgradeableReadLock(); try { if (State == ConnectionState.Connected && sendMessage && !timeout) { // Send disconnect message // Allocate memory HeapMemory memory = MemoryManager.AllocHeapMemory(1); // Write disconnect header memory.Buffer[0] = HeaderPacker.Pack(MessageType.Disconnect); // Send disconnect message SendInternal(new ArraySegment <byte>(memory.Buffer, 0, (int)memory.VirtualCount), true); // Release memory MemoryManager.DeAlloc(memory); } if (State != ConnectionState.Disconnected) { _stateLock.EnterWriteLock(); try { // Set the state to disconnected State = ConnectionState.Disconnected; // Release all memory Release(); } finally { _stateLock.ExitWriteLock(); } // Remove from global lookup Socket.RemoveConnection(this); // Send disconnect to userspace Socket.PublishEvent(new NetworkEvent() { Connection = this, Socket = Socket, Type = timeout ? NetworkEventType.Timeout : NetworkEventType.Disconnect, AllowUserRecycle = false, ChannelId = 0, Data = new ArraySegment <byte>(), InternalMemory = null, SocketReceiveTime = NetTime.Now, MemoryManager = MemoryManager, EndPoint = EndPoint }); } } finally { _stateLock.ExitUpgradeableReadLock(); } }