public void run() {
   long nextStart = System.currentTimeMillis();
   try {
     while (!dead) {
       long timeToSleep = nextStart - System.currentTimeMillis();
       if (timeToSleep > 10) Thread.sleep(timeToSleep);
       nextStart += Tickable.TIME_TICK;
       if ((CMProps.Bools.MUDSTARTED.property()) && (!CMLib.threads().isAllSuspended())) {
         globalTickCount++;
         for (Iterator<Exit> iter = exits.iterator(); iter.hasNext(); ) {
           Exit exit = iter.next();
           try {
             if (!exit.tick(globalTickCount)) exits.remove(exit);
           } catch (Exception e) {
             Log.errOut("ServiceEngine", e.toString());
           }
         }
         for (Iterator<TimeClock> iter = clocks.iterator(); iter.hasNext(); ) {
           TimeClock clock = iter.next();
           try {
             if (!clock.tick(globalTickCount)) clocks.remove(clock);
           } catch (Exception e) {
             Log.errOut("ServiceEngine", e.toString());
           }
         }
       }
     }
   } catch (InterruptedException e) {
   }
 }
 public void startTickDown(TickActer E) {
   if (E.nextAct() <= System.currentTimeMillis()) {
     CMClass.threadPool.execute(E);
     return;
   }
   tickActQueue.add(E);
   if (tickActQueue.first() == E) tickActThread.interrupt();
 }
 public void run() {
   while (true) {
     try {
       while (!tickActQueue.isEmpty()) {
         awake = false;
         TickActer next = tickActQueue.first();
         long timeToSleep = next.nextAct() - System.currentTimeMillis();
         if (timeToSleep > 0) Thread.sleep(timeToSleep);
         awake = true;
         nextTicker:
         if ((CMProps.Bools.MUDSTARTED.property()) && (!isSuspended)) {
           if (!tickActQueue.remove(next)) break nextTicker;
           CMClass.threadPool.execute(next);
         }
       }
     }
     /*try { next.tickAct(); }
     catch(Exception t) { Log.errOut("ServiceEngine",t); }*/
     catch (InterruptedException ioe) {
     }
     // If it was interrupted, it is most likely because we need to wake up for a new early
     // ticker, or the previous new ticker got baleeted.
     // Interruptions will only come if the thread is sleeping though.
     // NOTE: tickAct() should NEVER call a sleep (nor take any significant amount of time
     // anyways)!
     if (dead) {
       awake = false;
       break;
     }
     synchronized (tickActQueue) {
       while (tickActQueue.isEmpty())
         try {
           tickActQueue.wait();
         } catch (InterruptedException ioe) {
         }
     }
   }
 }
  /*
  	public void insertOrderDeathInOrder(DVector DV, long lastStart, String msg, Tick tock)
  	{
  		if(DV.size()>0)
  		for(int i=0;i<DV.size();i++)
  		{
  			if(((Long)DV.elementAt(i,0)).longValue()>lastStart)
  			{
  				DV.insertRowAt(i,Long.valueOf(lastStart),msg,tock);
  				return;
  			}
  		}
  		DV.addRow(Long.valueOf(lastStart),msg,tock);
  	}
  */
  public void checkHealth() {
    long lastDateTime = System.currentTimeMillis() - (5 * CoffeeTime.MILI_MINUTE);
    // long longerDateTime=System.currentTimeMillis()-(120*CoffeeTime.MILI_MINUTE);
    // thread.status("checking");

    ArrayList<TickArea> orderedDeaths = new ArrayList();
    thread.status("checking tick groups.");
    /*for(Iterator<Tick> e=ticks.iterator();e.hasNext();)
    {
    	Tick almostTock=e.next();
    	if((almostTock.awake)
    	&&(almostTock.lastStop<lastDateTime))
    	{
    		//insertOrderDeathInOrder(orderedDeaths,0,"LOCKED GROUP "+almostTock.tickObjectCounter+"! No further information.",almostTock);
    		delTickGroup(almostTock);
    		orderedDeaths.add(almostTock);	//"LOCKED GROUP "+almostTock.tickObjectCounter+"! No further information."
    		// no isDEBUGGING check -- just always let her rip.
    		Log.errOut(thread.getName(),"LOCKED TICK GROUP "+almostTock.tickObjectCounter);
    		thread.debugDumpStack(almostTock);
    	}
    }
    if(orderedDeaths.size()>0)
    {
    	thread.status("killing tick groups.");
    	for(int x=0;x<orderedDeaths.size();x++)
    	{
    		Tick almostTock=orderedDeaths.get(x);
    		ArrayList<TickActer> objs=new ArrayList();
    		try{
    			for(TickActer E : almostTock.tickers())
    				objs.add(E);
    		}catch(NoSuchElementException e){}
    		almostTock.shutdown();
    		//if(CMLib.threads() instanceof ServiceEngine)
    		//	((ServiceEngine)CMLib.threads()).
    		//delTickGroup(almostTock);
    		for(int i=0;i<objs.size();i++)
    			startTickDown(objs.get(i));
    	}
    	orderedDeaths.clear();
    }*/
    thread.status("checking areas.");
    for (Iterator<TickArea> e = areas.iterator(); e.hasNext(); ) {
      TickArea almostTock = e.next();
      if ((almostTock.awake) && (almostTock.lastStop < lastDateTime)) {
        delArea(almostTock);
        // orderedDeaths.add(almostTock);	//"LOCKED GROUP "+almostTock.tickObjectCounter+"! No
        // further information."
        almostTock.shutdown();
        Log.errOut(thread.getName(), "LOCKED TICK GROUP " + almostTock.tickObjectCounter);
        thread.debugDumpStack(almostTock);
        startArea(almostTock.clientObject, almostTock.TICK_TIME);
      }
    }
    /*
    		thread.status("Checking mud threads");
    		for(int m=0;m<CMLib.hosts().size();m++)
    		{
    			Vector badThreads=((MudHost)CMLib.hosts().elementAt(m)).getOverdueThreads();
    			if(badThreads.size()>0)
    			{
    				for(int b=0;b<badThreads.size();b++)
    				{
    					Thread T=(Thread)badThreads.elementAt(b);
    					String threadName=T.getName();
    					if(T instanceof Tickable)
    						threadName=((Tickable)T).ID()+" ("+((Tickable)T).ID()+"): "+((Tickable)T).getTickStatus();
    					thread.status("Killing "+threadName);
    					Log.errOut("Killing stray thread: "+threadName);
    					CMLib.killThread(T,100,1);
    				}
    			}
    		}
    		thread.status("Done checking threads");
    */
  }