SDL Forum Index
SDL
Simple DirectMedia Layer Forums
Reply to topic
using SDL_UserEvent with SDL_timer
Leonel Florín Selles
Guest

Reply with quote
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

Reply with quote
On Thu, Oct 29, 2009 at 03:47:43PM -0500, Leonel Florín Selles wrote:
Quote:
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.

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

Reply with quote
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Leonel Florín Selles wrote:
Quote:
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.

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

Reply with quote
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.



Quote:
On Thu, Oct 29, 2009 at 03:47:43PM -0500, Leonel Florín Selles wrote:
Quote:
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.

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



_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
using SDL_UserEvent with SDL_timer
Christopher Eineke
Guest

Reply with quote
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Leonel Florín Selles wrote:
Quote:
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.

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

Reply with quote
Quote:
----- Original Message ----

Quote:
From: Christopher Eineke
Subject: Re: [SDL] using SDL_UserEvent with SDL_timer

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Leonel Florín Selles wrote:
Quote:
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.

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):
<SNIP>
In C++, you need to add the (in-)appropriate casts:
<SNIP>
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.

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

Reply with quote
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:
Quote:

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
Re: using SDL_UserEvent with SDL_timer
WaltN


Joined: 21 Sep 2009
Posts: 20
Location: Vestal, New York USA
Reply with quote
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?
View user's profileSend private messageVisit poster's website
using SDL_UserEvent with SDL_timer
Mason Wheeler
Guest

Reply with quote
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


Joined: 21 Sep 2009
Posts: 20
Location: Vestal, New York USA
Reply with quote
Mason Wheeler wrote:
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.


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.)
View user's profileSend private messageVisit poster's website
using SDL_UserEvent with SDL_timer
Brian
Guest

Reply with quote
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

Quote:
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.)


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

WaltN


Joined: 21 Sep 2009
Posts: 20
Location: Vestal, New York USA
Reply with quote
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.
View user's profileSend private messageVisit poster's website
WaltN


Joined: 21 Sep 2009
Posts: 20
Location: Vestal, New York USA
Reply with quote
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.
View user's profileSend private messageVisit poster's website
using SDL_UserEvent with SDL_timer
Bob


Joined: 19 Sep 2009
Posts: 178
Reply with quote
On Wed, Nov 11, 2009 at 1:44 PM, WaltN wrote:
Quote:


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.



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

 
Quote:

Any suggestions?


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org




--
+-----------------------------------------------------------
+ Bob Pendleton: writer and programmer
+ email:          
+ web: www.TheGrumpyProgrammer.com
View user's profileSend private message
WaltN


Joined: 21 Sep 2009
Posts: 20
Location: Vestal, New York USA
Reply with quote
WaltN wrote:
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.


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?
View user's profileSend private messageVisit poster's website
using SDL_UserEvent with SDL_timer
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
All times are GMT  
Page 1 of 2  

  
  
 Reply to topic