context: // **********************************************************************
  //
  // Copyright (c) 2003-2011 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.
  //
  // **********************************************************************
  
  //
  // NOTE: We don't use C# timers, the API is quite a bit different from
  // the C++ & Java timers and it's not clear what is the cost of
  // scheduling and cancelling timers.
  //
      
  namespace IceInternal
  {
      using System;
      using System.Diagnostics;
      using System.Threading;
      using System.Collections.Generic;
  
      public interface TimerTask
      {
          void runTimerTask();
      }
  
      public sealed class Timer
      {
          public void destroy()
          {
              _m.Lock();
              try
              {
                  if(_instance == null)
                  {
                      return;
                  }
  
                  _instance = null;
                  _m.Notify();
              
                  _tokens.Clear();
                  _tasks.Clear();
              }
              finally
              {
                  _m.Unlock();
              }
  
              _thread.Join();
          }
  
          public void schedule(TimerTask task, long delay)
          {
              _m.Lock();
              try
              {
                  if(_instance == null)
                  {
                      throw new Ice.CommunicatorDestroyedException();
                  }
  
                  Token token = new Token(Time.currentMonotonicTimeMillis() + delay, ++_tokenId, 0, task);
  
                  try
                  {
                      _tasks.Add(task, token);
                      _tokens.Add(token, null);
                  }
                  catch(System.ArgumentException)
                  {
                      Debug.Assert(false);
                  }
              
                  if(token.scheduledTime < _wakeUpTime)
                  {
                      _m.Notify();
                  }
              }
              finally
              {
                  _m.Unlock();
              }
          }
  
          public void scheduleRepeated(TimerTask task, long period)
          {
              _m.Lock();
              try
              {
                  if(_instance == null)
                  {
                      throw new Ice.CommunicatorDestroyedException();
                  }
  
                  Token token = new Token(Time.currentMonotonicTimeMillis() + period, ++_tokenId, period, task);
  
                  try
                  {
                      _tasks.Add(task, token);
                      _tokens.Add(token, null);
                  }
                  catch(System.ArgumentException)
                  {
                      Debug.Assert(false);
                  }
  
                  if(token.scheduledTime < _wakeUpTime)
                  {
                      _m.Notify();
                  }
              }
              finally
              {
                  _m.Unlock();
              }
          } 
          
          public bool cancel(TimerTask task)
          {
              _m.Lock();
              try
              {
                  if(_instance == null)
                  {
                      return false;
                  }
  
                  Token token;
                  if(!_tasks.TryGetValue(task, out token))
                  {
                      return false;
                  }
                  _tasks.Remove(task);
                  _tokens.Remove(token);
                  return true;
              }
              finally
              {
                  _m.Unlock();
              }
          }
  
          //
          // Only for use by Instance.
          //
          internal Timer(IceInternal.Instance instance, ThreadPriority priority)
          {
              init(instance, priority, true);
          }
  
          internal Timer(IceInternal.Instance instance)
          {
              init(instance, ThreadPriority.Normal, false);
          }
  
          internal void init(IceInternal.Instance instance, ThreadPriority priority, bool hasPriority)
          {
              _instance = instance;
  
              string threadName = _instance.initializationData().properties.getProperty("Ice.ProgramName");
              if(threadName.Length > 0)
              {
                  threadName += "-";
              }
  
              _thread = new Thread(new ThreadStart(Run));
              _thread.IsBackground = true;
              _thread.Name = threadName + "Ice.Timer";
              if(hasPriority)
              {
                  _thread.Priority = priority;
              }
              _thread.Start();
          }
  
          public void Run()
          {
              Token token = null;
              while(true)
              {
                  _m.Lock();
                  try
                  {
                      if(_instance != null)
                      {
                          //
                          // If the task we just ran is a repeated task, schedule it
                          // again for execution if it wasn't canceled.
                          //
                          if(token != null && token.delay > 0)
                          {
                              if(_tasks.ContainsKey(token.task))
                              {
                                  token.scheduledTime = Time.currentMonotonicTimeMillis() + token.delay;
                                  _tokens.Add(token, null);
                              }
                          }
                      }
                      token = null;
  
                      if(_instance == null)
                      {
                          break;
                      }
  
                      if(_tokens.Count == 0)
                      {
                          _wakeUpTime = System.Int64.MaxValue;
                          _m.Wait();
                      }
              
                      if(_instance == null)
                      {
                          break;
                      }
                  
  
gt:                     while(_tokens.Count > 0 && _instance != null)