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="http://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        }