/*
* Copyright 2007 Sun Microsystems, Inc.
*
* This file is part of jVoiceBridge.
*
* jVoiceBridge is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation and distributed hereunder
* to you.
*
* jVoiceBridge 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the License file that accompanied this
* code.
*/
package com.sun.voip;
public class TickerBusyWait implements Ticker {
private String id;
private int timePeriod;
private long startTime;
private int count;
private int overSlept;
private int underSlept;
private int minDrift;
private int maxDrift;
private int totalDrift;
private long lastTime;
private int[] waitDistribution = new int[200];
private int totalWaitTime = 0;
private boolean armed;
public TickerBusyWait(String id) {
this.id = id;
}
public void arm(long delay, long timePeriod) {
this.timePeriod = (int) timePeriod;
startTime = System.currentTimeMillis();
lastTime = startTime;
minDrift = 0;
maxDrift = 0;
totalDrift = 0;
count = 0;
armed = true;
}
public void disarm() {
armed = false;
}
public void tick() throws TickerException {
if (!armed) {
throw new TickerException(id + " not armed");
}
long start = System.currentTimeMillis();
int drift = getDrift();
totalDrift += drift;
if (drift > maxDrift) {
maxDrift = drift;
}
if (drift < minDrift) {
minDrift = drift;
}
count++;
if (Logger.logLevel == -99) {
Logger.println("drift " + drift);
Logger.logLevel = 3;
}
if (drift > timePeriod) {
overSlept++;
return;
} else if (drift < -timePeriod) {
underSlept++;
}
do {
drift = getDrift();
while ((int) (System.currentTimeMillis() - lastTime) <
timePeriod) {
Thread.yield();
}
} while (drift < -timePeriod);
updateWaitDistribution(start);
}
private int getDrift() {
int actualElapsed = (int) (System.currentTimeMillis() - startTime);
int expectedElapsed = count * timePeriod;
return actualElapsed - expectedElapsed;
}
public int getMinDrift() {
return minDrift;
}
public int getMaxDrift() {
return maxDrift;
}
private void updateWaitDistribution(long start) {
int elapsed = (int) (System.currentTimeMillis() - start);
if (elapsed < 0) {
elapsed = 0;
} else if (elapsed >= waitDistribution.length) {
elapsed = waitDistribution.length - 1;
}
waitDistribution[elapsed]++;
totalWaitTime += elapsed;
}
public double getAvg() {
return ((double)(System.currentTimeMillis() - startTime)) / count;
}
public void printStatistics() {
if (count > 0) {
Logger.println(id
+ " average time between ticks "
+ ((float)(System.currentTimeMillis() - startTime) /
(float)count) + " ms");
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.println("Total calls to TickerBusyWait " + count);
Logger.println("OverSlept count " + overSlept);
Logger.println("UnderSlept count " + underSlept);
Logger.println("Minimum drift " + getMinDrift());
Logger.println("Maximum drift " + getMaxDrift());
Logger.println("Average drift " + (totalDrift / count));
Logger.println("");
Logger.println(id + " Wait time distribution");
Logger.println(id + " ms\tCount");
for (int i = 0; i < waitDistribution.length; i++) {
if (waitDistribution[i] != 0) {
Logger.println(id + " " + i + "\t"
+ waitDistribution[i]);
}
}
Logger.println("");
}
}
}
public static void main(String args[]) {
TickerBusyWait tickerBusyWait = new TickerBusyWait("Test");
tickerBusyWait.arm(RtpPacket.PACKET_PERIOD, RtpPacket.PACKET_PERIOD);
while (true) {
try {
tickerBusyWait.tick();
} catch (TickerException e) {
System.out.println("tick() failed! " + e.getMessage());
System.exit(1);
}
Logger.println(" avg " + tickerBusyWait.getAvg());
}
}
}