Den äldsta klassen

Likt många andra utvecklare har jag samlat på mig bra-att-ha-kod som jag återanvänder i alla möjliga sammanhang. Jag har en maven-modul som heter dcommons (d är en inledande bokstav som funkar bra tycker jag) som innehåller de klasser som är generiska. Det är inte många kvar nu då de flesta, som väl är, har ersatts av liknande i allmänt tillgängliga bibliotek, t.ex. Apache Commons. När jag i ett utfall av nostalgi utgrävde det absolut äldsta jag släpat med mig hela vägen till nutid, fann jag till min förtjusning en klass PassiveTimer, med anor bortåt 25 år bakåt i tiden.

Från början är det en C-implementation som konverterats till Java i slutet av 90-talet. PassiveTimer är en klass som används för att kolla om en förutbestämd tid har löpt ut eller ej. Man kan använda den t.ex. för att blinka med en lysdiod eller för att logga ackumulerade värden från höghastighetsräknare eller för att slänga upp en progressdialog om tråden tar mer än x sekunder på sig att exekvera jobbet.

Själva konceptet (kanske ett väl högtidligt epitet) härrör från PLC-system. Redan på 80-talet fann jag den mycket användbar när jag ägnade dagar och nätter åt att bygga styrsystem för verkstadsindustrin i *NIX och C.

Hemma används den varje dag i motorvärmarstyrningen för min hustrus bil. Emellanåt får jag ett litet värmande SMS, Tack för varm bil idag också puss.

Användningen är trivial. Exemplet exekverar en kontroll-loop med en frekvens och ”blinkar” med en variabel med en annan frekvens:

    PassiveTimer t = new PassiveTimer(TIME_PERIOD_MSEC);
    boolean ledState = false;

    while (true) {
      System.out.println("getRemainingTime()=" + t.getRemainingTime());

      if (t.hasExpired()) {
        ledState = !ledState;
        System.out.println("expired,led=" + ledState);
        t.restart();
      }
      Thread.sleep(POLL_TIME_MSEC);
    }

Output blir:

getRemainingTime()=1000
getRemainingTime()=800
getRemainingTime()=600
getRemainingTime()=399
getRemainingTime()=199
getRemainingTime()=0
expired,led=true
getRemainingTime()=800
getRemainingTime()=600
getRemainingTime()=399
getRemainingTime()=199
getRemainingTime()=0
expired,led=false
...

Koden:

/*
 * Created by Daniel Marell, originating from C code 1987, re-implemented in Java 1997
 */
package se.marell.dcommons;

/**
 * A timer starts measuring time from a certain value and counts down towards zero.
 * It doesn't call back nor execute in a separate thread. You have to explicit ask
 * if the PassiveTimer has expired.
 */
public class PassiveTimer {
  private long duration;
  private boolean hold;
  private long startTime;
  private long holdTime;

  /**
   * Construct a PassiveTimer counting down from the specified duration
   * @param msec Number of milliseconds util timer expires
   */
  public PassiveTimer(long msec) {
    duration = msec;
    hold = false;
    holdTime = 0;
    startTime = System.currentTimeMillis();
  }

  /**
   * Restart timer with current duration
   */
  public void restart() {
    startTime = System.currentTimeMillis();
    hold = false;
  }

  /**
   * Restart timer with new duration
   * @param msec Number of milliseconds util timer expires
   */
  public void restart(long msec) {
    duration = msec;
    restart();
  }

  /**
   * Set timer duration
   * @param msec Number of milliseconds util timer expires
   */
  public void setDuration(long msec) {
    duration = msec;
  }

  /**
   * Has timer expired?
   * @return true if timer has expired
   */
  public boolean hasExpired() {
    return !hold && System.currentTimeMillis() >= (startTime + duration);
  }

  /**
   * Remaining time
   * @return Number of milliseconds util timer expires
   */
  public long getRemainingTime() {
    if (hasExpired()) {
      return 0;
    }
    if (hold) {
      return startTime + duration - holdTime;
    }
    return startTime + duration - System.currentTimeMillis();
  }

  /**
   * Force timer to expire
   */
  public void forceExpire() {
    startTime = System.currentTimeMillis() - duration;
    hold = false;
  }

  /**
   * Freeze/resume timer
   * @param flag Freezes timer at current duration if true, releases if false
   */
  public void hold(boolean flag) {
    if (flag == hold) {
      return;
    }
    if (flag) {
      holdTime = System.currentTimeMillis();
    } else {
      startTime += System.currentTimeMillis() - holdTime;
    }
    hold = flag;
  }

  /**
   * PassiveTimer running?
   * @return true if timer is running
   */
  public boolean isRunning() {
    return !hold && !hasExpired();
  }

  /**
   * PassiveTimer duration
   * @return Number of milliseconds for the initial duration. If timer is restarted this is the new duration.
   */
  public long getDuration() {
    return duration;
  }
}

IT Consultant at CAG Edge. Cloud and Continuous Delivery specialist, software developer and architect, Node.js, Java.

Publicerad i Java

Kategorier

WP to LinkedIn Auto Publish Powered By : XYZScripts.com