<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>Hiccups in main loop that get worse over time</title>
		<link>http://www.allegro.cc/forums/view/616994</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Wed, 09 Aug 2017 09:12:12 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>My main loop uses a frame timer which I turn off when the display loses focus and re-enable when it comes back.  I&#39;ve noticed a problem where if I step away for an hour or so and come back, I get these long hiccups (stalls) that seem to get longer the longer I wasn&#39;t paying attention to the window.  I&#39;m not sure if it happens whether or not the display has lost focus, but I may try testing it with the window focused tonight.  Has anyone run into this?  It doesn&#39;t make much sense.  I don&#39;t know what the system is doing during these stalls.  I realized that during these stalls, frames still seem to be processed, just not displayed.  So the effect is extreme frame skipping every second for a moment and then smooth action for about a second and then another skip and so on.</p><p>Forth source:</p><pre>
\ Universal main loop
\  Skips rendering frames if logic takes too long (up to 4 frames are skipped)
\  You can disable the frame timer to save CPU when making editors etc
\  When the window is switched away from the timer will be disabled, and re-enabled when
\    it regains focus.
\  The loop has some common controls:
\    F12 - break the loop
\    ALT-F4 - quit the process
\    ALT-ENTER - toggle fullscreen
\    TILDE - toggles a flag called INFO, doesn&#39;t do anything on its own.

\ Values
0 value #frames \ frame counter.
0 value renderr
0 value steperr
0 value alt?  \ part of fix for alt-enter bug when game doesn&#39;t have focus
0 value breaking?
0 value lag  \ completed ticks
0 value &#39;go
0 value &#39;step
0 value &#39;render

\ Flags
variable info  \ enables debugging mode display
variable allowwin  allowwin on
variable fs    \ is fullscreen enabled?
variable interact   \ if on, cmdline will receive keys.  check if false before doing game input, if needed.

create fse  /ALLEGRO_ANY_EVENT /allot  \ fullscreen event
#999 constant EVENT_FULLSCREEN 

: poll  pollKB  pollJoys  [defined] dev [if] pause [then] ;
: break  true to breaking? ;
: -break  false to breaking? ;
: unmount  ( -- )
    1-1
    0 0 displayw displayh al_set_clipping_rectangle
    ALLEGRO_ADD ALLEGRO_ALPHA ALLEGRO_INVERSE_ALPHA  ALLEGRO_ADD ALLEGRO_ONE ALLEGRO_ONE al_set_separate_blender
    display al_set_target_backbuffer ;

[defined] dev [if]
    variable (catch)
    : try  dup -exit  sp@ cell+ &gt;r  code&gt; catch (catch) !  r&gt; sp!  (catch) @ ;
[else]
    : try  dup -exit call 0 ;
[then]

\ : alt?  evt ALLEGRO_KEYBOARD_EVENT-modifiers @ ALLEGRO_KEYMOD_ALT and ;
: std
  etype ALLEGRO_EVENT_DISPLAY_RESIZE = if
    -timer  display al_acknowledge_resize  +timer  \ we have to turn off the timer to avoid a race condition
                                                   \ where bitmaps aren&#39;t recreated before trying to draw to them
  then
  etype ALLEGRO_EVENT_DISPLAY_SWITCH_OUT = if  -timer  -audio  then
  etype ALLEGRO_EVENT_DISPLAY_SWITCH_IN = if  clearkb  +timer   +audio  false to alt?
    eventq al_flush_event_queue
    [defined] dev [if] interact on [then] then
  etype ALLEGRO_EVENT_DISPLAY_CLOSE = if  0 ExitProcess  then
  etype ALLEGRO_EVENT_KEY_DOWN = if
    evt ALLEGRO_KEYBOARD_EVENT-keycode @ case
      &lt;alt&gt;    of  true to alt?  endof
      &lt;altgr&gt;  of  true to alt?  endof
      &lt;enter&gt;  of  alt? -exit  fs toggle  endof
      &lt;f4&gt;     of  alt? -exit  0 ExitProcess endof
      &lt;f12&gt;    of  break  endof
      &lt;tilde&gt;  of  alt? -exit  info toggle  endof
    endcase
  then
  etype ALLEGRO_EVENT_KEY_UP = if
    evt ALLEGRO_KEYBOARD_EVENT-keycode @ case
      &lt;alt&gt;    of  false to alt?  endof
      &lt;altgr&gt;  of  false to alt?  endof
    endcase
  then ;


: fsflag  fs @ allowwin @ not or ;
: ?fserr  0= if fs off  &quot; Fullscreen is not supported by your driver.&quot; alert  then ;
variable winx  variable winy
: ?poswin   \ save/restore window position when toggling in and out of fullscreen
    display al_get_display_flags ALLEGRO_FULLSCREEN_WINDOW and if
        fs @ 0= if  r&gt; call  display winx @ winy @ al_set_window_position  then
    else
        fs @ if     display winx winy al_get_window_position  then
    then ;

variable newfs
: ?fs
    ?poswin  display ALLEGRO_FULLSCREEN_WINDOW fsflag al_toggle_display_flag ?fserr
    fs @  newfs @  &lt;&gt; if
        fse EVENT_FULLSCREEN emit-user-event
    then
    fs @ newfs ! ;

defer ?overlay  &#39; noop is ?overlay  \ render ide
defer ?system   &#39; noop is ?system   \ system events

: render  unmount  &#39;render try to renderr ;
: step  &#39;step try to steperr ;
private:
    : update?  timer? if  lag dup -exit drop  then  eventq al_is_event_queue_empty  lag 4 &gt;= or ;
    : wait  eventq evt al_wait_for_event ;
    : ?render  update? -exit  1 +to #frames  ?fs  render  unmount  ?overlay  al_flip_display
        0 to lag ;
    : ?step  etype ALLEGRO_EVENT_TIMER = if  1 +to lag   poll  step  then ;
    : /ok  resetkb  -break  &gt;display  +timer  render ;
    : ok/  eventq al_flush_event_queue -timer  &gt;ide  -break ;
public:

: render&gt;  r&gt;  to &#39;render ;  ( -- &lt;code&gt; )  ( -- )
: step&gt;  r&gt;  to &#39;step ;  ( -- &lt;code&gt; )  ( -- )
: go&gt;  r&gt; to &#39;go   0 to &#39;step ;  ( -- &lt;code&gt; )  ( -- )

: ok
    /ok
    begin
        wait
        begin
            std  ?system  &#39;go try drop  ?step  ?render
            eventq evt al_get_next_event 0=  breaking? or
        until  ?render  \ again for sans timer
    breaking? until
    ok/ ;

:noname  0 0 0.5 clear-to-color ; &gt;code  to &#39;render

</pre><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (roger levy)</author>
		<pubDate>Sat, 05 Aug 2017 06:54:21 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>What OS and what specific version of Allegro?</p><p>Thanks! Definitely an interesting problem...
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Chris Katko)</author>
		<pubDate>Sat, 05 Aug 2017 08:41:54 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Allegro 5.2.3, Windows 10
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (roger levy)</author>
		<pubDate>Sat, 05 Aug 2017 09:28:46 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Try switching between OpenGL and Direct3D. Not sure how you do that in Elvish though...</p><p>I&#39;ll try reproducing it with <span class="source-code">ex_draw_bitmap</span> &#39;s event loop, although I&#39;m not sure how well that maps to yours.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Sat, 05 Aug 2017 10:00:32 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>The principle is pretty simple.  Create a timer using the refresh rate retrieved from Allegro.  In the event loop, when the timer event fires do game logic and increment a &quot;lag&quot; variable for frame-skipping.  When all events are processed, or if lag is over 4, do a render, and reset lag.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (roger levy)</author>
		<pubDate>Sat, 05 Aug 2017 10:05:45 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Any luck on your end? I feel like I&#39;ll need to learn a bit of Forth to verify that it&#39;s not your code. Have you tried calling <span class="source-code"><a href="http://www.allegro.cc/manual/al_stop_timer"><span class="a">al_stop_timer</span></a></span> instead of just setting <span class="source-code">timer</span> to false?
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Wed, 09 Aug 2017 07:21:04 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>-TIMER and +TIMER actually do stop and restart the timer.    Sorry, I didn&#39;t include their definitions.  (If you don&#39;t already know this about Forth, there are no reserved characters except for white space, so those are actually the names of functions I&#39;ve written.)</p><p>What I&#39;ve done is add event logging so the next time I experience the issue (which I haven&#39;t yet, strangely) I&#39;ll be able to see if a bunch of events are being generated during a hiccup, which is my current theory.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (roger levy)</author>
		<pubDate>Wed, 09 Aug 2017 09:12:12 +0000</pubDate>
	</item>
</rss>
