package javacodebook.thread.metronome;


class MetronomeThread extends Thread {
    Metronome metronome;
    boolean stop;
    int period;
    
    MetronomeThread(Metronome metronome, int period) {
        this.metronome = metronome;
        this.stop      = false;
        this.period    = period;
    }
    
    void stopExecution() {
        stop = true;
    }
    
    public void run() {
        long start = System.currentTimeMillis();
        while(!stop) {
            try {
                // Schlafen, bis eine Periode um ist. Es kann vorkommen, dass
                // bei der Benachrichtigung von vielen Observern Zeit verloren
                // geht. Diese verlorene Zeit wird errechnet und der Thread
                // entsprechend kürzer schlafen gelegt.
                long now = System.currentTimeMillis();
                long left = (period*1000) - ((now-start)%(period*1000));
                // Da die sleep-Methode manchmal etwas zu früh aufwacht, müssen
                // wir verhinden, dass die Observer in einer Periode zwei mal
                // benachrichtigt werden. Ein Puffer von 500 ms reicht.
                if (left < 500)
                    left += (period*1000);
                sleep(left);
                metronome.periodElapsed();
            }
            catch (Exception ignore) {}
        }
    }
}
