context: // **********************************************************************
  //
  // Copyright (c) 2003-2013 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.
  //
  // **********************************************************************
  
  #if !SILVERLIGHT
  namespace IceInternal
  {
      using System;
      using System.Collections.Generic;
      using System.Diagnostics;
      using System.Net;
      using System.Threading;
  
      public class EndpointHostResolver
      {
          internal EndpointHostResolver(Instance instance)
          {
              _instance = instance;
              _protocol = instance.protocolSupport();
              _preferIPv6 = instance.preferIPv6();
              _thread = new HelperThread(this);
              updateObserver();
              if(instance.initializationData().properties.getProperty("Ice.ThreadPriority").Length > 0)
              {
                  ThreadPriority priority = IceInternal.Util.stringToThreadPriority(
                                             instance.initializationData().properties.getProperty("Ice.ThreadPriority"));
                  _thread.Start(priority);
              }
              else
              {
                  _thread.Start(ThreadPriority.Normal);
              }
          }
  
          
          public List<Connector> resolve(string host, int port, Ice.EndpointSelectionType selType, EndpointI endpoint)
          {
              //
              // Try to get the addresses without DNS lookup. If this doesn't
              // work, we retry with DNS lookup (and observer).
              //
              List<EndPoint> addrs = Network.getAddresses(host, port, _protocol, selType, _preferIPv6, false);
              if(addrs.Count > 0)
              {
                  return endpoint.connectors(addrs);
              }
  
              Ice.Instrumentation.CommunicatorObserver obsv = _instance.initializationData().observer;
              Ice.Instrumentation.Observer observer = null;
              if(obsv != null)
              {
                  observer = obsv.getEndpointLookupObserver(endpoint);
                  if(observer != null)
                  {
                      observer.attach();
                  }
              }
      
              List<Connector> connectors = null;
              try 
              {
                  connectors = endpoint.connectors(Network.getAddresses(host, port, _protocol, selType, _preferIPv6, 
                                                                        true));
              }
              catch(Ice.LocalException ex)
              {
                  if(observer != null)
                  {
                      observer.failed(ex.ice_name());
                  }
                  throw ex;
              }
              finally
              {
                  if(observer != null)
                  {
                      observer.detach();
                  }
              }
              return connectors;
          }
  
          public void resolve(string host, int port, Ice.EndpointSelectionType selType, EndpointI endpoint, 
                              EndpointI_connectors callback)
          {
              //
              // Try to get the addresses without DNS lookup. If this doesn't work, we queue a resolve
              // entry and the thread will take care of getting the endpoint addresses.
              //
              try
              {
                  List<EndPoint> addrs = Network.getAddresses(host, port, _protocol, selType, _preferIPv6, false);
                  if(addrs.Count > 0)
                  {
                      callback.connectors(endpoint.connectors(addrs));
                      return;
                  }
              }
              catch(Ice.LocalException ex)
              {
                  callback.exception(ex);
                  return;
              }
  
              _m.Lock();
              try
              {
                  Debug.Assert(!_destroyed);
  
                  ResolveEntry entry = new ResolveEntry();
                  entry.host = host;
                  entry.port = port;
                  entry.selType = selType;
                  entry.endpoint = endpoint;
                  entry.callback = callback;
  
                  Ice.Instrumentation.CommunicatorObserver obsv = _instance.initializationData().observer;
                  if(obsv != null)
                  {
                      entry.observer = obsv.getEndpointLookupObserver(endpoint);
                      if(entry.observer != null)
                      {
                          entry.observer.attach();
                      }
                  }
  
                  _queue.AddLast(entry);
                  _m.Notify();
              }
              finally
              {
                  _m.Unlock();
              }
          }
  
          public void destroy()
          {
              _m.Lock();
              try
              {
                  Debug.Assert(!_destroyed);
                  _destroyed = true;
                  _m.Notify();
              }
              finally
              {
                  _m.Unlock();
              }
          }
  
          public void joinWithThread()
          {
              if(_thread != null)
              {
                  _thread.Join();
              }
          }
  
          public void run()
          {
              while(true)
              {
                  ResolveEntry r;
                  Ice.Instrumentation.ThreadObserver threadObserver;
  
                  _m.Lock();
                  try
                  {
                      while(!_destroyed && _queue.Count == 0)
                      {
                          _m.Wait();
                      }
  
                      if(_destroyed)
                      {
                          break;
                      }
  
                      r = _queue.First.Value;
                      _queue.RemoveFirst();
                      threadObserver = _observer;
                  }
                  finally
                  {
                      _m.Unlock();
                  }
  
                  try
                  {
                      if(threadObserver != null)
                      {
                          threadObserver.stateChanged(Ice.Instrumentation.ThreadState.ThreadStateIdle, 
                                                      Ice.Instrumentation.ThreadState.ThreadStateInUseForOther);
                      }
  
                      r.callback.connectors(r.endpoint.connectors(Network.getAddresses(r.host, 
                                                                                       r.port, 
                                                                                       _protocol, 
                                                                                       r.selType, 
                                                                                       _preferIPv6, 
                                                                                       true)));
  
                      if(threadObserver != null)
                      {
                          threadObserver.stateChanged(Ice.Instrumentation.ThreadState.ThreadStateInUseForOther, 
                                                      Ice.Instrumentation.ThreadState.ThreadStateIdle);
                      }
                  }
                  catch(Ice.LocalException ex)
                  {
                      if(r.observer != null)
                      {
                          r.observer.failed(ex.ice_name());
                      }
                      r.callback.exception(ex);
                  }
                  finally
                  {
                      if(r.observer != null)
                      {
                          r.observer.detach();
                      }
                  }
              }
  
              foreach(ResolveEntry entry in _queue)
              {
                  Ice.CommunicatorDestroyedException ex = new Ice.CommunicatorDestroyedException();
                  entry.callback.exception(ex);
                  if(entry.observer != null)
                  {
                      entry.observer.failed(ex.ice_name());
                      entry.observer.detach();
                  }
              }
              _queue.Clear();
  
              if(_observer != null)
              {
                  _observer.detach();
              }
          }
  
          public void
          updateObserver()
          {
              _m.Lock();
              try
              {
                  Ice.Instrumentation.CommunicatorObserver obsv = _instance.initializationData().observer;
  
gt:                 if(obsv != null)