[Mono-devel-list] Reworked Patch of Timer

Ben Maurer bmaurer at ximian.com
Fri Jun 24 11:41:21 EDT 2005


General issues: 
      * Tabs are still off. Something is funky with your editor ;-) 
      * Please follow the mono coding guidelines
        (http://mono-project.com/Coding_Guidelines) 
      * Avoid being verbose in declarations (private static ArrayList
        timers = null; can be static ArrayList timers -- private is the
        default, the fields are 0 inited)

Specific issues:

> +		private TimerTask GetTimerTask(Timer timer)
> +		{
> +			
> +			foreach (TimerTask timerTask in timers)
> +			{
> +				if (timerTask.timer == timer)
> +					return timerTask;
> +			}
> +			return null;
> +		}


This made me think of something that has been obvious: the Timer and
TimerTask do not need to be split. Just add Timers to the array


> +			Timer timer = this;
> +			lock(lockObj)
> +			{
> +				if (timers.Count == 1)
> +				{
> +					// i am the last timer to be disposed.
> +					if (t != null && t.IsAlive) 
> +						t = null;
> +					timers = null;
> +					initialized = false;
> +					triggeredOnce = false;
> +					
> +				}
> +				else
> +				{
> +					// then there are other timers.
> +					TimerTask timerTask = GetTimerTask(timer);
> +					timeToWaitDirty = true;
> +					timers.Remove(timerTask);								  	    Monitor.Pulse(lockObj);
> +				 }	
>  			}
> 

This code could be alot cleaner. I'd like to see it so that you don't
have to test timers.Count == 1. The way to do this would be:

      * Remove the timer from the list (like one normally would)
      * Pulse the lock

In the timer loop thread, the wait will be pulsed. Then, in this code:


> +					if (timeToWait == -1)
> +						return;// handle with some sleep..

You should set t = null. That will take the place of `initialized'.


> +		private static int GetTimeToNextEvent()
> +		{
> +			if (timers.Count == 0)
> +				return -1; // all timers are gone!
> +			if (timeToWaitDirty)
> +			{
> +				if (!triggeredOnce)
> +					time = FindMinDueTime();
> +				else
> +					time = FindMinPeriod();
> +				timeToWaitDirty = false;
> +			}
> +			return time;	
> +		}

This code is hard to understand, and somewhat non obvious. It is not
clear how DueTime works when there are multiple timers, for example.


> +		private static int FindMinDueTime()
> +		{
> +			int minDueTime = 2147483647;

No magic numbers please.


> +			if (initialized)
> +                                Add(callback,state,(int)dueTime,(int)period,this);
> +                         else
> +                                Initialize(callback,state,(int)dueTime,(int)period);

Race here (you might see that it was initialized, then the thread dies,
you add the task and it doesn't get run). I think this code should be
cleaned up a bit. I'd phrase it like:

Add (...)
if (t == null) {
	// start the thread.
}

public Timer (TimerCallback callback, object state, long dueTime, long
period)

should probably call directly to the int ctor with : this (...). That
way, you can avoid having the Init method all together. 


>  #if NET_2_0
>  		public Timer (TimerCallback callback)
>  		{
> -			Init (callback, this, Timeout.Infinite, Timeout.Infinite);
> +			if (initialized)
> +                                Add(callback,state,(int)dueTime,(int)period,this);
> +                         else
> +                                Initialize(callback,state,(int)dueTime,(int)period);
>  		}
>  #endif

This doesn't even compile on 2.0. You should use : this so that you can
put code in only one ctor.

-- Ben




More information about the Mono-devel-list mailing list