view dwtx/dwtxhelper/Timer.d @ 167:862b05e0334a

Add a wrapper for Thread
author Frank Benoit <benoit@tionex.de>
date Tue, 09 Sep 2008 15:59:16 +0200
parents 86617aa6b5dd
children 1470d66733fa
line wrap: on
line source

module dwtx.dwtxhelper.Timer;

import dwtx.dwtxhelper.TimerTask;
import tango.util.container.CircularList;
import dwtx.dwtxhelper.JThread;
import tango.core.sync.Mutex;
import tango.core.sync.Condition;
import tango.time.Time;
import tango.time.Clock;

class Timer {

    alias CircularList!( TimerTask ) ListType;

    private JThread thread;
    private ListType schedules;
    private Mutex mutex;
    private Condition cond;
    private bool isCanceled = false;

    this(){
        this(false);
    }
    this(bool isDaemon){
        mutex = new Mutex();
        cond = new Condition( mutex );

        schedules = new ListType();
        thread = new JThread( &run );
        thread.setDaemon( isDaemon );
        thread.start();
    }
    private void run(){

        while( !isCanceled ){
            TimerTask timerTask = null;
            synchronized(mutex){
                bool isReady = false;
                do{
                    if( isCanceled ){
                        return;
                    }

                    if( schedules.size() is 0 ){
                        cond.wait();
                    }
                    else{
                        timerTask = schedules.head();
                        TimeSpan toWait = timerTask.executionTime - Clock.now();
                        if( toWait.interval() > 0 ){
                            cond.wait( toWait.interval() );
                        }
                        else{
                            schedules.removeHead();
                            isReady = true;
                        }
                    }
                }while( !isReady );
            }
            if( timerTask ){
                timerTask.run();
                if( timerTask.period.millis > 0 ){
                    timerTask.executionTime += timerTask.period;
                    synchronized(mutex){
                        int index = 0;
                        foreach( tt; schedules ){
                            if( tt.executionTime > timerTask.executionTime ){
                                break;
                            }
                            index++;
                        }
                        schedules.addAt( index, timerTask );
                    }
                }
            }
        }
    }
    void   cancel(){
        synchronized(mutex){
            isCanceled = true;
            cond.notifyAll();
        }
    }
    void   schedule(TimerTask task, long delay){
        scheduleAtFixedRate( task, delay, 0 );
    }
    void   scheduleAtFixedRate(TimerTask task, long delay, long period){
        assert( task );
        task.executionTime = Clock.now + TimeSpan.millis(delay);
        task.timer = this;
        synchronized(mutex){
            int index = 0;
            foreach( tt; schedules ){
                if( tt.executionTime > task.executionTime ){
                    break;
                }
                index++;
            }
            schedules.addAt( index, task );
            cond.notifyAll();
        }
    }

//     void   schedule(TimerTask task, Date time){}
//     void   schedule(TimerTask task, Date firstTime, long period){}
//     void   schedule(TimerTask task, long delay, long period){}
//     void   scheduleAtFixedRate(TimerTask task, Date firstTime, long period){}
}