context: // **********************************************************************
  //
  // Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved.
  //
  // This copy of Ice is licensed to you under the terms described in the
  // ICE_LICENSE file included in this distribution.
  //
  // **********************************************************************
  
  namespace Ice
  {
      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.Diagnostics;
      using System.Text;
      using System.Threading;
      using Ice.Instrumentation;
  
      public sealed class ConnectionI :
          IceInternal.EventHandler, IceInternal.ResponseHandler, IceInternal.CancellationHandler, Connection
      {
          public interface StartCallback
          {
              void connectionStartCompleted(ConnectionI connection);
              void connectionStartFailed(ConnectionI connection, LocalException ex);
          }
  
          private class TimeoutCallback : IceInternal.TimerTask
          {
              public TimeoutCallback(ConnectionI connection)
              {
                  _connection = connection;
              }
  
              public void runTimerTask()
              {
                  _connection.timedOut();
              }
  
              private Ice.ConnectionI _connection;
          }
  
          public void start(StartCallback callback)
          {
              try
              {
                  lock(this)
                  {
                      //
                      // The connection might already be closed if the communicator was destroyed.
                      //
                      if(_state >= StateClosed)
                      {
                          Debug.Assert(_exception != null);
                          throw _exception;
                      }
  
                      if(!initialize(IceInternal.SocketOperation.None) || !validate(IceInternal.SocketOperation.None))
                      {
                          _startCallback = callback;
                          return;
                      }
  
                      //
                      // We start out in holding state.
                      //
                      setState(StateHolding);
                  }
              }
              catch(LocalException ex)
              {
                  exception(ex);
                  callback.connectionStartFailed(this, _exception);
                  return;
              }
  
              callback.connectionStartCompleted(this);
          }
  
          public void startAndWait()
          {
              try
              {
                  lock(this)
                  {
                      //
                      // The connection might already be closed if the communicator was destroyed.
                      //
                      if(_state >= StateClosed)
                      {
                          Debug.Assert(_exception != null);
                          throw _exception;
                      }
  
                      if(!initialize(IceInternal.SocketOperation.None) || !validate(IceInternal.SocketOperation.None))
                      {
                          //
                          // Wait for the connection to be validated.
                          //
                          while(_state <= StateNotValidated)
                          {
                              System.Threading.Monitor.Wait(this);
                          }
  
                          if(_state >= StateClosing)
                          {
                              Debug.Assert(_exception != null);
                              throw _exception;
                          }
                      }
  
                      //
                      // We start out in holding state.
                      //
                      setState(StateHolding);
                  }
              }
              catch(LocalException ex)
              {
                  exception(ex);
                  waitUntilFinished();
                  return;
              }
          }
  
          public void activate()
          {
              lock(this)
              {
                  if(_state <= StateNotValidated)
                  {
                      return;
                  }
  
                  if(_acmLastActivity > -1)
                  {
                      _acmLastActivity = IceInternal.Time.currentMonotonicTimeMillis();
                  }
                  setState(StateActive);
              }
          }
  
          public void hold()
          {
              lock(this)
              {
                  if(_state <= StateNotValidated)
                  {
                      return;
                  }
  
                  setState(StateHolding);
              }
          }
  
          // DestructionReason.
          public const int ObjectAdapterDeactivated = 0;
          public const int CommunicatorDestroyed = 1;
  
          public void destroy(int reason)
          {
              lock(this)
              {
                  switch(reason)
                  {
                      case ObjectAdapterDeactivated:
                      {
                          setState(StateClosing, new ObjectAdapterDeactivatedException());
                          break;
                      }
  
                      case CommunicatorDestroyed:
                      {
                          setState(StateClosing, new CommunicatorDestroyedException());
                          break;
                      }
                  }
              }
          }
  
          public void close(bool force)
          {
              lock(this)
              {
                  if(force)
                  {
                      setState(StateClosed, new ForcedCloseConnectionException());
                  }
                  else
                  {
                      //
                      // If we do a graceful shutdown, then we wait until all
                      // outstanding requests have been completed. Otherwise,
                      // the CloseConnectionException will cause all outstanding
                      // requests to be retried, regardless of whether the
                      // server has processed them or not.
                      //
                      while(_asyncRequests.Count != 0)
                      {
                          System.Threading.Monitor.Wait(this);
                      }
  
                      setState(StateClosing, new CloseConnectionException());
                  }
              }
          }
  
          public bool isActiveOrHolding()
          {
              lock(this)
              {
                  return _state > StateNotValidated && _state < StateClosing;
              }
          }
  
          public bool isFinished()
          {
              //
              // We can use TryLock here, because as long as there are still
              // threads operating in this connection object, connection
              // destruction is considered as not yet finished.
              //
              if(!System.Threading.Monitor.TryEnter(this))
              {
                  return false;
              }
  
              try
              {
                  if(_state != StateFinished || _dispatchCount != 0)
                  {
                      return false;
                  }
  
                  Debug.Assert(_state == StateFinished);
                  return true;
              }
              finally
              {
                  System.Threading.Monitor.Exit(this);
              }
          }
  
          public void throwException()
          {
              lock(this)
              {
                  if(_exception != null)
                  {
                      Debug.Assert(_state >= StateClosing);
                      throw _exception;
                  }
              }
          }
  
          public void waitUntilHolding()
          {
              lock(this)
              {
                  while(_state < StateHolding || _dispatchCount > 0)
                  {
                      System.Threading.Monitor.Wait(this);
                  }
              }
          }
  
          public void waitUntilFinished()
          {
              lock(this)
              {
                  //
                  // We wait indefinitely until the connection is finished and all
                  // outstanding requests are completed. Otherwise we couldn't
                  // guarantee that there are no outstanding calls when deactivate()
                  // is called on the servant locators.
                  //
                  while(_state < StateFinished || _dispatchCount > 0)
                  {
                      System.Threading.Monitor.Wait(this);
                  }
  
                  Debug.Assert(_state == StateFinished);
  
                  //
                  // Clear the OA. See bug 1673 for the details of why this is necessary.
                  //
                  _adapter = null;
              }
          }
  
          public void updateObserver()
          {
              lock(this)
              {
                  if(_state < StateNotValidated || _state > StateClosed)
                  {
                      return;
                  }
  
                  Debug.Assert(_instance.initializationData().observer != null);
                  _observer = _instance.initializationData().observer.getConnectionObserver(initConnectionInfo(),
                                                                                            _endpoint,
                                                                                            toConnectionState(_state),
                                                                                            _observer);
                  if(_observer != null)
                  {
                      _observer.attach();
                  }
                  else
                  {
                      _writeStreamPos = -1;
                      _readStreamPos = -1;
                  }
              }
          }
  
          public void monitor(long now, IceInternal.ACMConfig acm)
          {
              lock(this)
              {
                  if(_state != StateActive)
                  {
                      return;
                  }
  
                  //
                  // We send a heartbeat if there was no activity in the last
                  // (timeout / 4) period. Sending a heartbeat sooner than
                  // really needed is safer to ensure that the receiver will
                  // receive in time the heartbeat. Sending the heartbeat if
                  // there was no activity in the last (timeout / 2) period
                  // isn't enough since monitor() is called only every (timeout
                  // / 2) period.
                  //
                  // Note that this doesn't imply that we are sending 4 heartbeats
                  // per timeout period because the monitor() method is sill only
                  // called every (timeout / 2) period.
                  //
                  if(acm.heartbeat == ACMHeartbeat.HeartbeatAlways ||
                     (acm.heartbeat != ACMHeartbeat.HeartbeatOff && _writeStream.isEmpty() &&
  
gt:                     now >= (_acmLastActivity + acm.timeout / 4)))