001 package com.croftsoft.core.util.loop; 002 003 import com.croftsoft.core.animation.updater.FrameRateUpdater; 004 import com.croftsoft.core.math.MathConstants; 005 006 /********************************************************************** 007 * Uses System nanoTime() to measure time between calls. 008 * 009 * @version 010 * $Date: 2008/02/15 21:18:30 $ 011 * @since 012 * 2005-08-04 013 * @author 014 * <a href="https://www.croftsoft.com/">David Wallace Croft</a> 015 **********************************************************************/ 016 017 public final class NanoTimeLoopGovernor 018 implements LoopGovernor 019 /////////////////////////////////////////////////////////////////////// 020 /////////////////////////////////////////////////////////////////////// 021 { 022 023 private long periodNanos; 024 025 private long nextTime; 026 027 /////////////////////////////////////////////////////////////////////// 028 /////////////////////////////////////////////////////////////////////// 029 030 /********************************************************************** 031 * Test method. 032 **********************************************************************/ 033 public static void main ( String [ ] args ) 034 throws Exception 035 /////////////////////////////////////////////////////////////////////// 036 { 037 LoopGovernor loopGovernor = new NanoTimeLoopGovernor ( 85.0 ); 038 039 FrameRateUpdater frameRateUpdater = new FrameRateUpdater ( true ); 040 041 long startTime = System.nanoTime ( ); 042 043 int i = 0; 044 045 for ( ; i < 10000; i++ ) 046 { 047 loopGovernor.govern ( ); 048 049 frameRateUpdater.update ( null ); 050 } 051 052 long stopTime = System.nanoTime ( ); 053 054 long deltaTime = stopTime - startTime; 055 056 deltaTime = deltaTime / MathConstants.NANOSECONDS_PER_SECOND; 057 058 System.out.println ( ( ( double ) i ) / deltaTime + " " + i ); 059 } 060 061 /////////////////////////////////////////////////////////////////////// 062 // constructor methods 063 /////////////////////////////////////////////////////////////////////// 064 065 /********************************************************************** 066 * Constructs a LoopGovernor with the specified target frequency. 067 * 068 * @param frequency 069 * 070 * The targeted loop frequency in loops per second. 071 **********************************************************************/ 072 public NanoTimeLoopGovernor ( double frequency ) 073 /////////////////////////////////////////////////////////////////////// 074 { 075 setFrequency ( frequency ); 076 } 077 078 /********************************************************************** 079 * Initializes with a periodNanos of zero (maximum frequency). 080 **********************************************************************/ 081 public NanoTimeLoopGovernor ( ) 082 /////////////////////////////////////////////////////////////////////// 083 { 084 // periodNanos = 0 085 } 086 087 /////////////////////////////////////////////////////////////////////// 088 /////////////////////////////////////////////////////////////////////// 089 090 /********************************************************************** 091 * If the frequency is set to Double.POSITIVE_INFINITY, periodNanos 092 * will be set to zero. 093 **********************************************************************/ 094 public void setFrequency ( final double frequency ) 095 /////////////////////////////////////////////////////////////////////// 096 { 097 if ( frequency <= 0.0 ) 098 { 099 throw new IllegalArgumentException ( "frequency <= 0.0" ); 100 } 101 102 if ( frequency == Double.POSITIVE_INFINITY ) 103 { 104 periodNanos = 0; 105 } 106 else 107 { 108 periodNanos = Math.round ( 109 MathConstants.NANOSECONDS_PER_SECOND / frequency ); 110 } 111 } 112 113 public void setPeriodNanos ( final long periodNanos ) 114 /////////////////////////////////////////////////////////////////////// 115 { 116 if ( periodNanos < 0L ) 117 { 118 throw new IllegalArgumentException ( "periodNanos < 0" ); 119 } 120 121 this.periodNanos = periodNanos; 122 } 123 124 /////////////////////////////////////////////////////////////////////// 125 // interface LoopGovernor method 126 /////////////////////////////////////////////////////////////////////// 127 128 public void govern ( ) 129 throws InterruptedException 130 /////////////////////////////////////////////////////////////////////// 131 { 132 final long currentTime = System.nanoTime ( ); 133 134 long delayTime = nextTime - currentTime; 135 136 if ( delayTime < 0 ) 137 { 138 delayTime = 0; 139 140 nextTime = currentTime + periodNanos; 141 } 142 else 143 { 144 nextTime += periodNanos; 145 } 146 147 final long delayMillis 148 = delayTime / MathConstants.NANOSECONDS_PER_MILLISECOND; 149 150 final int delayNanos = ( int ) 151 ( delayTime % MathConstants.NANOSECONDS_PER_MILLISECOND ); 152 153 Thread.sleep ( delayMillis, delayNanos ); 154 } 155 156 /////////////////////////////////////////////////////////////////////// 157 /////////////////////////////////////////////////////////////////////// 158 }