+++ /dev/null
-/*
- * Copyright (c) 2001 The Anthill Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-package peersim.edsim;
-
-import peersim.core.Node;
-import peersim.core.CommonState;
-import peersim.config.Configuration;
-import peersim.config.IllegalParameterException;
-
-/**
- * The Heap data structure used to maintain events "sorted" by
- * scheduled time and to obtain the next event to be executed.
- *
- * @author Alberto Montresor
- * @version $Revision: 1.10 $
- */
-public class Heap implements PriorityQ {
-
-//--------------------------------------------------------------------------
-// Constants
-//--------------------------------------------------------------------------
-
-/**
- * This parameter specifies how many
- * bits are used to order events that occur at the same time. Defaults
- * to 8. A value smaller than 8 causes an IllegalParameterException.
- * Higher values allow for a better discrimination, but reduce
- * the maximal time steps that can be simulated.
- * @config
- */
-private static final String PAR_PBITS = "pbits";
-private static final String PAR_PBITS_LEGACY = "simulation.timebits";
-
-/**
- * Specifies the initial capacity of the heap. Defaults to 65536.
- * @config
- */
-private static final String PAR_SIZE = "size";
-
-
-//--------------------------------------------------------------------------
-// Fields
-//--------------------------------------------------------------------------
-
-// The following arrays are four heaps ordered by time. The alternative
-// approach (i.e. to store event objects) requires much more memory,
-// and based on some tests that I've done is not really much faster.
-
-/** Event component of the heap */
-private Object[] events;
-
-/** Time component of the heap */
-private long[] times;
-
-/** Node component of the heap */
-private Node[] nodes;
-
-/** Pid component of the heap */
-private byte[] pids;
-
-/** Number of elements */
-private int size;
-
-/** Singleton event object used to return (event, time, node, pid) tuples */
-private final Event ev = new Event();
-
-/** The number of bits reserved to order event with the same timestamp */
-private final int pbits;
-
-/** The mask to test whether the time value fits into the range we can
-represent */
-private final long overflowMask;
-
-//--------------------------------------------------------------------------
-// Contructor
-//--------------------------------------------------------------------------
-
-/**
- * Initializes a new heap using defaults.
- */
-public Heap() {
- this(""); // "" is not a valid prefix for a component
-}
-
-//--------------------------------------------------------------------------
-
-/**
- * Initializes a new heap using the configuration.
- */
-public Heap(String prefix) {
-
- int size = Configuration.getInt(prefix+"."+PAR_SIZE,65536);
-
- // some complex stuff to deal with legacy parameter names...
- if( !Configuration.contains(PAR_PBITS_LEGACY) )
- pbits = Configuration.getInt(prefix+"."+PAR_PBITS,8);
- else
- {
- pbits = Configuration.getInt(PAR_PBITS_LEGACY);
- if( Configuration.contains(prefix+"."+PAR_PBITS) )
- throw new IllegalParameterException(PAR_PBITS_LEGACY,
- "Your configuration file contains both "+
- prefix+"."+PAR_PBITS+ " and "+
- PAR_PBITS_LEGACY+"; please remove "+
- PAR_PBITS_LEGACY);
- }
-
- if (pbits < 8 || pbits >= 31) {
- throw new IllegalParameterException(prefix+"."+PAR_PBITS,
- "This parameter should be >= 8 or < 31");
- }
- overflowMask = ~maxTime();
- events = new Object[size];
- times = new long[size];
- nodes = new Node[size];
- pids = new byte[size];
-}
-
-//--------------------------------------------------------------------------
-// Methods
-//--------------------------------------------------------------------------
-
-/**
- * Returns the current number of events in the system.
- */
-public int size()
-{
- return size;
-}
-
-//--------------------------------------------------------------------------
-
-/**
- * Add a new event, to be scheduled at the specified time.
- *
- * @param time the time at which this event should be scheduled
- * @param event the object describing the event
- * @param node the node at which the event has to be delivered
- * @param pid the protocol that handles the event
- */
-public void add(long time, Object event, Node node, byte pid)
-{
- add(time,event,node,pid,CommonState.r.nextInt(1 << pbits));
-}
-
-//--------------------------------------------------------------------------
-
-/**
- * Add a new event, to be scheduled at the specified time.
- *
- * @param time the time at which this event should be scheduled
- * @param event the object describing the event
- * @param node the node at which the event has to be delivered
- * @param pid the protocol that handles the event
- */
-public void add(long time, Object event, Node node, byte pid, long priority)
-{
- if( (time&overflowMask) != 0 ) throw new
- IllegalArgumentException("Time overflow: time="+time);
-//XXX should we test priority overflow? How much does it cost?
-
- time = (time << pbits) | priority;
-
- size++;
- int pos = size;
- put(pos, time, event, node, pid);
- while (pos > 1 && getTime(pos / 2) > time) {
- swap(pos, pos / 2);
- pos = pos / 2;
- }
-}
-
-//--------------------------------------------------------------------------
-
-/**
- * Removes the first event in the heap and returns it.
- * Note that, to avoid garbage collection, a singleton instance of
- * the Event class is used. This means that data contained in the
- * returned event are overwritten when a new invocation of this
- * method is performed.
- * @return first event or null if size is zero
- */
-public Event removeFirst() {
-
- if(size==0) return null;
-
- ev.time = times[0] >> pbits;
- ev.event = events[0];
- ev.node = nodes[0];
- ev.pid = pids[0];
- swap(1, size);
- size--;
- minHeapify(1);
- return ev;
-}
-
-//--------------------------------------------------------------------------
-
-public long maxTime() { return Long.MAX_VALUE >> pbits; }
-
-//--------------------------------------------------------------------------
-
-public long maxPriority() { return (1L << pbits)-1; }
-
-//--------------------------------------------------------------------------
-
-/**
- * Prints the time values contained in the heap.
- */
-public String toString()
-{
- StringBuffer buffer = new StringBuffer();
- buffer.append("[Size: " + size + " Times: ");
- for (int i=1; i <= size; i++) {
- buffer.append(getTime(i)+",");
- }
- buffer.append("]");
- return buffer.toString();
-}
-
-
-//--------------------------------------------------------------------------
-// Private methods
-//--------------------------------------------------------------------------
-
-/**
- *
- */
-private void minHeapify(int index)
-{
- // The time to be placed of the current node
- long time = getTime(index);
- // Left, right children of the current index
- int l,r;
- // Their associated time
- long lt, rt;
- // The minimum time between val, lt, rt
- long mintime;
- // The index of the mininum time
- int minindex = index;
- do {
- index = minindex;
- mintime = time;
- l = index << 1;
- r = l + 1;
- if (l <= size && (lt = getTime(l)) < mintime) {
- minindex = l;
- mintime = lt;
- }
- if (r <= size && (rt = getTime(r)) < mintime) {
- minindex = r;
- mintime = rt;
- }
- if (minindex != index) {
- swap(minindex, index);
- }
- } while (minindex != index);
-}
-
-//--------------------------------------------------------------------------
-
-/**
- *
- */
-private void swap(int i1, int i2) {
-
- i1--;
- i2--;
-
- Object te = events[i1];
- events[i1] = events[i2];
- events[i2] = te;
-
- long tt = times[i1];
- times[i1] = times[i2];
- times[i2] = tt;
-
- Node tn = nodes[i1];
- nodes[i1] = nodes[i2];
- nodes[i2] = tn;
-
- byte tp = pids[i1];
- pids[i1] = pids[i2];
- pids[i2] = tp;
-}
-
-//--------------------------------------------------------------------------
-
-/**
- *
- */
-private long getTime(int index) {
- /* Compute first and second index, and return the value */
- index--;
- return times[index];
-}
-
-//--------------------------------------------------------------------------
-
-/**
- *
- */
-private void put(int index, long time, Object event, Node node, byte pid) {
-
- index--;
- if (index >= events.length) {
- doubleCapacity();
- }
- events[index] = event;
- times[index] = time;
- nodes[index] = node;
- pids[index] = pid;
-}
-
-//--------------------------------------------------------------------------
-
-/**
- *
- */
-private void doubleCapacity() {
- int oldsize = events.length;
- int newsize = oldsize*2;
- Object[] te = new Object[newsize];
- System.arraycopy(events, 0, te, 0, oldsize);
- events = te;
- long[] tt = new long[newsize];
- System.arraycopy(times, 0, tt, 0, oldsize);
- times = tt;
- Node[] tn = new Node[newsize];
- System.arraycopy(nodes, 0, tn, 0, oldsize);
- nodes = tn;
- byte[] tp = new byte[newsize];
- System.arraycopy(pids, 0, tp, 0, oldsize);
- pids = tp;
-}
-
-//--------------------------------------------------------------------------
-// Testing
-//--------------------------------------------------------------------------
-
-/*
-public static void main(String[] args) {
- Random random = new Random();
- Heap heap = new Heap();
- int rep = 1000000;
- if( args.length > 0 ) rep = Integer.parseInt(args[0]);
- int[] values1 = new int[rep];
- long[] values2 = new long[rep];
- for (int i = 0; i < rep; i++) {
- values1[i] = random.nextInt(1000000000);
- }
-
- long time1 = System.currentTimeMillis();
- for (int i = 0; i < rep; i++) {
- heap.add(values1[i], null, null, (byte) 1);
- }
- long time2 = System.currentTimeMillis();
- System.out.println("Inserting: " + (time2-time1));
-
- time1 = System.currentTimeMillis();
- for (int i = 0; i < rep; i++) {
- values2[i] = heap.removeFirst().time;
- }
- time2 = System.currentTimeMillis();
- System.out.println("Removing: " + (time2-time1));
-
- Arrays.sort(values1);
- for (int i=0; i<rep; i++) {
- if (values1[i] != values2[i])
- System.out.print("+");
- }
-}
-*/
-
-} // END Heap