![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Leonel FlorÃn Selles
Guest
![]() |
![]() |
hello:
how can i call a function from a timer using a SDL_UserEvent, i know how this work but what i don't know is how to connect the function to the SDL_UserEvent. _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||
|
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Bill Kendrick
Guest
![]() |
![]() |
On Thu, Oct 29, 2009 at 03:47:43PM -0500, Leonel Florín Selles wrote:
In your event loop, you watch for events of type 'SDL_USEREVENT'. If... I understand your question. (Which I might not.) -- -bill! Sent from my computer _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Christopher Eineke
Guest
![]() |
![]() |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512 Leonel Florín Selles wrote:
There are two parts to this solution: 1. Set up the timer. When the timer fires, don't actually invoke the function in the timer callback. Instead, you push an user event into the queue with a code (SDL_UserEvent.code) that you somehow associate with the function that you want to call. This schedules the actual work to be done for later. (The "hard IRQ.") You could do this with a kind of manager module or #define's. (I'm not offering judgment whether these are good methods or not.) 2. In your event loop, you check for user events. When you find one, examine its code and call the function that you earlier identified, optionally with parameters provided. (The "soft IRQ.") This approach is similar to the top-half-bottom-half approach in operating systems, where the top half "actually responds to the hardware interrupt and a bottom half (or "soft" irq) that is scheduled by the top half to do additional processing." (http://lwn.net/Articles/302043/) - -- - -*- Christopher C. Eineke -*- Email: -*- - -*- Independent Software Developer -*- Cell: 1-519-852-3409 -*- - -*- -*- Home: 1-226-663-3651 -*- -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEAREKAAYFAkrqHwQACgkQPOmqd0kEEbu4IgCgm7LDOpW5vCxW74Rzs3pgZj2r nNQAoM665vSyP/xFrxgW/+usqHW3rUtl =p4wL -----END PGP SIGNATURE----- _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Leonel FlorÃn Selles
Guest
![]() |
![]() |
Well friends, i'll going to repeat the question, I have a callback function
where I want to call an other function, and I want do that from SDL_UserEvent, but what i know is that SDL_UserEvent is an structure that have 4 kind of data or more SDL_UserEvent -> type SDL_UserEvent -> code SDL_UserEvent -> void * data1 SDL_UserEvent -> void * data2 and the last one i don't remember, well how using this i can connect this UserEvent with a function.
_______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||
|
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Christopher Eineke
Guest
![]() |
![]() |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512 Leonel FlorÃn Selles wrote:
In C, you may cast the pointer to the function to a void*, but you must ensure that when you "recover" the pointer to the function its signature is the same (see items 766-768 @ http://c0x.coding-guidelines.com/6.3.2.3.html): #include <stdio.h> int foo(int bar) { return bar; } int main() { void* function = &foo; int (*fooz)(int) = function; printf("3 == %d\n", fooz(3)); return 0; } In C++, you need to add the (in-)appropriate casts: #include <stdio.h> int foo(int bar) { return bar; } int main() { void* function = reinterpret_cast<void*>(&foo); int (*fooz)(int) = reinterpret_cast<int (*)(int)>(function); printf("3 == %d\n", fooz(3)); return 0; } But that's like sledgehammering a rose petal. You're completely foregoing type safety and it's a nightmare to debug. And on-top, it doesn't work for class methods. One approach is to store instances that adhere to an interface in a vector somewhere: #include <vector> struct IEvtCB { virtual int bar(void*, void*) = 0; }; struct EvtCB_1 : public IEvtCB { virtual int foo(void*, void*) { return bar; } }; std::vector<EvtCB_1*> vec; int main() { vec.push_back(new EvtCB_1()); return 0; } then find the corresponding instance in the vector and invoke the the method in question: /* ... */ if (evt.type == SDL_USEREVENT) { if (evt.user.code > -1) { IEvtCB& cb = vec[evt.user.code]; int ret = cb.bar(evt.user.data1, evt.user.data2); } else { /* something's amiss */ } } /* ... */ Another way is to use a functor (google it) that encapsulates the function or method call and that you can then store in data1 or data2 and cast back to a functor later on. - -- - -*- Christopher C. Eineke -*- Email: -*- - -*- Independent Software Developer -*- Cell: 1-519-852-3409 -*- - -*- -*- Home: 1-226-663-3651 -*- -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEAREKAAYFAkrqWhgACgkQPOmqd0kEEbtvAwCgpVEFBdecm+I97Xc1Dym6bwvZ J2gAoIv9191GdGVU3n1veJhYRjx2q5Kz =Zexz -----END PGP SIGNATURE----- _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Mason Wheeler
Guest
![]() |
![]() |
Hmm. In Delphi, a method pointer is represented by a record (struct) composed of two pointers: one to the function and one to the object instance. I notice the SDL_UserEvent struct here has two miscellaneous data pointers for general use. I don't know too much about C++ method pointers, but is there any way you could use them for that purpose? _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||||||
|
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Brian
Guest
![]() |
![]() |
C++ member function pointers are tricky beasts. For one thing, they
aren't required to be the same size as a void pointer. In fact, they often *are* 8 or 16 bytes on 32 bit compilers. You can wrap them in a struct with a virtual function, and use template hackery to generate the boilerplate (or use boost::function<>). For simpler tasks, you can wrap the member function in a free function: template<class T, void (T::*function)()> void wrapper( T *instance) { ((instance) ->* (function)) (); } This would require more work to support varying return types and parameters, but for one or two of each it might be a simpler alternative to boost::function. Still, technically I believe casting any function to void * is illegal, at least in C++: http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.8 On Fri, Oct 30, 2009 at 3:33 AM, Mason Wheeler wrote:
SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|
![]() |
Re: using SDL_UserEvent with SDL_timer | ![]() |
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Mason Wheeler
Guest
![]() |
![]() |
Well, just off the top of my head, an AV at $FFFFFFFF is a null pointer dereference. It's trying to access something at offset -1 from the pointer's location. Look for some object that gets freed while the window's being resized and then recreated afterwards.
From: WaltN To: Sent: Wed, November 11, 2009 11:44:52 AM Subject: Re: [SDL] using SDL_UserEvent with SDL_timer Christopher Eineke wrote: There are two parts to this solution: 1. Set up the timer. When the timer fires, don't actually invoke the function in the timer callback. Instead, you push an user event into the queue with a code (SDL_UserEvent.code) that you somehow associate with the function that you want to call. This schedules the actual work to be done for later. (The "hard IRQ.") You could do this with a kind of manager module or #define's. (I'm not offering judgment whether these are good methods or not.) 2. In your event loop, you check for user events. When you find one, examine its code and call the function that you earlier identified, optionally with parameters provided. (The "soft IRQ.") I've been using this method. But, when I try it with SDL 1.3, although it works nicely for a constant-sized window, it fails with an access violation (consistently at location FFFFFFFF) when resizing the window. I've noticed that while you are dragging the window border events are inhibited until you release the mouse button. Then a flock of resize event sequences or (resize, expose) sequences (depending on whether you're making the window smaller or larger, respectively) become available in the SDL event queue. I'm firing the timer every three seconds, and it seems like the failure may be occurring when the timer fires. The timer callback function isn't the culprit because it works fine when I'm not resizing. Because all the resize events are batched, I am unable to work around this problem. Any suggestions? |
||||||||||
|
![]() |
Re: using SDL_UserEvent with SDL_timer | ![]() |
WaltN
![]() |
![]() |
Unfortunately, although it's constant at location FFFFFFFF on my system, it's at 10299D2F on a buddy's. I should add that if I (via a control block) tell the timer callback to bypass pushing a user event onto the queue, the failure does not occur. But, of course, I've lost my only element of control -- the user event. I'll have to take a look at the bowels of the SDL 1.3 timer event handling code to see if I can spot anything. Is there any SDL 1.3 event that comes back to the SDL event queue (the one that's accessable via the API) WHILE the border is actually being dragged? (Note that my posting above points out that resize and possibly expose events are batched and made available after the window border is released.) |
||||||||||||
|
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Brian
Guest
![]() |
![]() |
Hello.
I believe this is an OS issue. I found, under windows at least, that SDL applications are literally frozen during resize (and window movement IIRC). This is why the events appear to be batched, its only when the window is released that all the events are actually delivered because the main event loop is allowed to run again. A few years ago I found a hack that could be used against SDL 1.2 ( http://www.gamedev.net/community/forums/topic.asp?topic_id=428022 ). Its nasty, but it did the job - on Windows at least. I have no idea whether it would work in SDL 1.3, or even against newer versions of SDL 1.2. Might be an avenue worth investigating though... -- Brian
|
||||||||||||
|
![]() |
![]() |
WaltN
![]() |
![]() |
I get the drift, and it looks very promising. I think I can use the event filter to set a flag (any time there's a resize event) which causes the timer callback to bypass pushing a user event onto the event queue. When the SDL event queue empties out, I'll "re-enable" the timer. I'll give it a try and report back. Thanks Brian.
|
||||||||||
|
![]() |
![]() |
WaltN
![]() |
![]() |
That sure does work nicely with my compiled test case. Problem solved there.
With my APL code (interpreted), the problem is alleviated. But, if I'm very slllloooowwww with a border drag or if I crank up the timer rate, it does crash quite readily. I've got one more trick up my sleeve before I give up. Interesting observation: With APL one core is moderately busy just executing the event loop. If I drag the border to do a resize, a second core comes into the picture. With the compiled C code, I see no change when I drag the border to resize. Leads me to speculate that my problem with APL is inter-task synchronization. The unpredictability of the problem had me thinking in that direction also. |
||||||||||
|
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Bob
![]() |
![]() |
On Wed, Nov 11, 2009 at 1:44 PM, WaltN wrote:
You might want to check to see how many events are being queued up. The SDL event queue has a fixed length of 128. Once it is full any additional events are just dumped until items have been removed from the queue. If for some odd reason you are letting the queue fill up you can see some very odd bugs. Bob Pendleton
-- +----------------------------------------------------------- + Bob Pendleton: writer and programmer + email: + web: www.TheGrumpyProgrammer.com |
||||||||||||||
|
![]() |
![]() |
WaltN
![]() |
![]() |
I apologize for the delay in getting back to this (over a month). I fell, fractured a hip, and it's taken me this long to get back to APL and SDL. I implemented an event filter, as suggested earlier, and queued no resize events. Also, I set a flag indicating that sizing is now going on. I ignore any user events associated with timers when that flag is set. That solves the crash problem, but introduces another question: How do I know when a resizing action is complete? Since all resize events are filtered out, there's no resize event queued upon end-of-resize. What I did was recognize that, if the event queue is empty, resizing can't be going on. Hence, in my idle-time section, I toggle the resizing flag and call OnResize if the resize flag is set. I see that Bug 666 deals with this and was fixed as of Rel. 5408. (I'm using 4703.) Does this fix have some mechanism included that senses end of resize? |
||||||||||||
|
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Sam Lantinga
![]() |
![]() |
Windows will post resize events in a tight loop and not return to the application until the resize is complete. The SDL fix will simply leave the last resize event in the queue. If you're grabbing them asynchronously, you'll see the events in the queue, but only as fast as you poll.
On Thu, Dec 17, 2009 at 11:59 AM, WaltN wrote:
-- -Sam Lantinga, Founder and President, Galaxy Gameworks LLC |
||||||||||||
|
![]() |
![]() |
WaltN
![]() |
![]() |
I think this is stable for me now that I'm running SVN 5431 (which includes fix for Bug 666) and have implemented disabling posting of user events while resizing. But, this morning, I discovered that a long, drawn out move of a window results in a crash that reminds me of the behavior with resize. And, after disabling posing of user events while moving, the problem went away.
Perhaps move requires a fix similar to that for resize? |
||||||||||
|
![]() |
using SDL_UserEvent with SDL_timer | ![]() |
Sam Lantinga
![]() |
![]() |
Very likely. Thanks for the heads up, I'll add a similar fix for move as well.
See ya! On Wed, Dec 23, 2009 at 11:10 AM, WaltN wrote:
-- -Sam Lantinga, Founder and President, Galaxy Gameworks LLC _______________________________________________ SDL mailing list http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org |
||||||||||||
|