All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.named_data.jndn.impl.DelayedCallTable Maven / Gradle / Ivy

/**
 * Copyright (C) 2015-2018 Regents of the University of California.
 * @author: Jeff Thompson 
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 * A copy of the GNU Lesser General Public License is in the file COPYING.
 */

package net.named_data.jndn.impl;

import java.util.ArrayList;
import net.named_data.jndn.util.Common;

/**
 * DelayedCallTable is an internal class used by the Node implementation of
 * callLater to store callbacks and call them when they time out.
 */
public class DelayedCallTable {
  /**
   * Call callback.run() after the given delay. This adds to the delayed call
   * table which is used by callTimedOut().
   * @param delayMilliseconds The delay in milliseconds.
   * @param callback This calls callback.run() after the delay.
   */
  public synchronized final void
  callLater(double delayMilliseconds, Runnable callback)
  {
    Entry entry = new Entry(delayMilliseconds, callback);
    // Insert into table_, sorted on getCallTime().
    // Search from the back since we expect it to go there.
    int i = table_.size() - 1;
    while (i >= 0) {
      if ((table_.get(i)).getCallTime() <= entry.getCallTime())
        break;
      --i;
    }
    // Element i is the greatest less than or equal to
    // entry.getCallTime(), so insert after it.
    table_.add(i + 1, entry);
  }

  /**
   * Call and remove timed-out callback entries. Since callLater does a sorted
   * insert into the delayed call table, the check for timed-out entries is
   * quick and does not require searching the entire table. This synchronizes on
   * the delayed call table when checking it, but not when calling the callback.
   */
  public final void
  callTimedOut()
  {
    // nowOffsetMilliseconds_ is only used for testing.
    double now = Common.getNowMilliseconds() + nowOffsetMilliseconds_;
    // table_ is sorted on _callTime, so we only need to process the timed-out
    // entries at the front, then quit.
    while (true) {
      Entry entry;
      // Lock while we check and maybe pop the element at the front.
      synchronized(this) {
        if (table_.isEmpty())
          break;
        entry = table_.get(0);
        if (entry.getCallTime() > now)
          // It is not time to call the entry at the front of the list, so finish.
          break;
        table_.remove(0);
      }

      // The lock on table_ is removed, so call the callback.
      entry.callCallback();
    }
  }

  /**
   * Set the offset for when prepareCommandInterestName() gets the current time,
   * which should only be used for testing.
   * @param nowOffsetMilliseconds The offset in milliseconds.
   */
  public final void
  setNowOffsetMilliseconds_(double nowOffsetMilliseconds)
  {
    nowOffsetMilliseconds_ = nowOffsetMilliseconds;
  }

  /**
   * Entry holds the callback and other fields for an entry in the delayed call
   * table.
   */
  private static class Entry {
    /**
     * Create a new DelayedCallTable.Entry and set the call time based on the
     * current time and the delayMilliseconds.
     * @param delayMilliseconds The delay in milliseconds.
     * @param callback This calls callback.run() after the delay.
     */
    public Entry(double delayMilliseconds, Runnable callback)
    {
      callback_ = callback;
      callTime_ = Common.getNowMilliseconds() + delayMilliseconds;
    }

    /**
     * Get the time at which the callback should be called.
     * @return The call time in milliseconds, similar to
     * Common.getNowMilliseconds().
     */
    public final double
    getCallTime() { return callTime_; }

    /**
     * Call the callback given to the constructor. This does not catch
     * exceptions.
     */
    public final void
    callCallback() { callback_.run(); }

    private final Runnable callback_;
    private final double callTime_;
  }

  private final ArrayList table_ = new ArrayList();
  private double nowOffsetMilliseconds_ = 0;
  // This is to force an import of net.named_data.jndn.util.
  private static Common dummyCommon_ = new Common();
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy