# Source: src/main/js/common/TaskLooper.js

    /**
     * Run a task in a fixed period loop.
     */
    class TaskLooper {

      /**
       * Build the looper with a function to invoke on a fixed period loop.
       *
       * @param {function} task - the task function to invoke
       */
      constructor(task) {
        this._task = task;
      }

      /**
       * Get the task function to invoke on a fixed period loop.
       *
       * @return {function} the task function
       */
      getTask() {
        return this._task;
      }

      /**
       * Start the task loop.
       *
       * @param {int} periodInMs the loop period in milliseconds
       * @return {TaskLooper} this class for chaining
       */
      start(periodInMs) {
        this._periodInMs = periodInMs;
        if (this._isStarted) return this;
        this._isStarted = true;

        // start looping
        this._runLoop();
        return this;
      }

      /**
       * Indicates if looping.
       *
       * @return {boolean} true if looping, false otherwise
       */
      isStarted() {
        return this._isStarted;
      }

      /**
       * Stop the task loop.
       */
      stop() {
        this._isStarted = false;
      }

      /**
       * Set the loop period in milliseconds.
       *
       * @param {int} periodInMs the loop period in milliseconds
       */
      setPeriodInMs(periodInMs) {
        this._periodInMs = periodInMs;
      }

      async _runLoop() {
        if (this._isLooping) return;
        this._isLooping = true;
        let that = this;
        while (this._isStarted) {
          let startTime = Date.now();
          await this._task();
          if (this._isStarted) await new Promise(function(resolve) { setTimeout(resolve, that._periodInMs - (Date.now() - startTime)); });
        }
        this._isLooping = false;
      }
    }

    module.exports = TaskLooper;