Allegro 8.0 Infinite Loop Stalling

Discussion of Common Lisp
Post Reply
Harnon
Posts: 78
Joined: Wed Jul 30, 2008 9:59 am

Allegro 8.0 Infinite Loop Stalling

Post by Harnon » Sun Feb 01, 2009 7:06 am

I'm trying to create a mouse polling loop in a thread. For an easy example of my problem, consider this code:

Code: Select all

(portable-threads::spawn-thread 
 "MOUSE"
 (lambda ()
   (loop 
    ; (print "HI" #.*standard-output*)
     (handler-case
         (poll-mouse 
           nil
          (:button (print "button press" #.*standard-output*))
          (:scroll (print "scroll" #.*standard-output*)))
         (error () ))
)))
This will produce a very noticeable stall in allegro lisp (as in it almost freezes).
However, if I comment in the (print "HI" #.*standard-output*) the thread appears to not slow down Allegro in any manner and, most importantly of all, every time i push the mouse button it correctly outputs the "button press" event. Same for scroll.

I tried adding a (sleep .01) in the loop, but it is still freezing. Notice that you have to add

Code: Select all

(setf (sys::thread-control :clock-event-delta) 10)
in order to get down to sleeps of .01 seconds.

(sleep .1) seems to be to long of a time and doesn't work because each event, I think, is being overwritten by another event which has occurred.

So I'm at a loss of how to imitate the anti-freezing affect of print, because i don't actually want something printed out on the screen. I guessed that what print does was slow down the loop so it wouldn't stall, but sleep, which I thought would do the same thing, doesn't work for less than .1 seconds because it starts stalling allegro lisp.

Notice that the same effect can be replicated by running

Code: Select all

(portable-threads::spawn-thread
  "test"
 (lambda () 
   (loop 
     ;(print "HI" #.*standard-output*) makes the loop here not stall
      (+ 2 3))))

EDIT: Sorry, I'm using Allegro 8.1 under Windows XP. Oh, and actually when i use .1 seconds it will sporadically print button press events and will eventually print a whole slew of them, inferring that the c library i'm using does store events. (I'm using manymouse)

findinglisp
Posts: 447
Joined: Sat Jun 28, 2008 7:49 am
Location: Austin, TX
Contact:

Re: Allegro 8.0 Infinite Loop Stalling

Post by findinglisp » Sun Feb 01, 2009 8:24 pm

I don't use Allegro and can't really tell you for sure, but it strikes me that Allegro might be using "green threads" to implement its portable threading library on your particular platform. It's just a guess, but having worked with similar systems before, you might have to explicitly yield the CPU at various points in other to give other threads a chance to run. It might be the case that I/O is a point where they automatically yield. I would search the Allegro documentation to see if it discusses how it does scheduling for its library and whether you need to explicitly yield the CPU during long computations.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/

blandest
Posts: 19
Joined: Mon Jun 30, 2008 1:22 am

Re: Allegro 8.0 Infinite Loop Stalling

Post by blandest » Mon Feb 02, 2009 1:29 am

Why are you using #.*standard-output* ? You could probably get rid of the #. (but maybe I'm wrong).
Also, the output stream parameter to #'print defaults to *standard-output*, so you may remove it altogether.
Yes, this does not help you :)

Harnon
Posts: 78
Joined: Wed Jul 30, 2008 9:59 am

Re: Allegro 8.0 Infinite Loop Stalling

Post by Harnon » Mon Feb 02, 2009 7:06 pm

Thank you a million times!!!! :D :D :D :D
You're absolutetly right. All i had to do was add (portable-threads:thread-yield) and everything worked!!
Oh, and just in case anyone starts using threads, you do in fact have to use #. because otherwise the thread will default to its own *standard-output*, and you won't see output. I tried after you asked, i knew there was a reason why i was doing it :D

dmitry_vk
Posts: 96
Joined: Sat Jun 28, 2008 8:01 am
Location: Russia, Kazan
Contact:

Re: Allegro 8.0 Infinite Loop Stalling

Post by dmitry_vk » Mon Feb 02, 2009 11:33 pm

Harnon wrote: Oh, and just in case anyone starts using threads, you do in fact have to use #. because otherwise the thread will default to its own *standard-output*, and you won't see output.
Using #. is a bad thing. It is a read-evaluation read-macro which means that the thread will output to the stream that was the *standard-output* at the time of compilation.
Special variables bindings are not inherited by new threads, so *standard-output* and other threads are set to their values. It would be better to capture the output stream in a lexically scoped variable:

Code: Select all

(let ((stream *stanard-output*))
 (portable-threads::spawn-thread
  ... (print "button-press" stream) ... ))
Other dynamic variables should be used likewise

Post Reply