Peeping events from a new thread

Since I have corrected my issues with OpenGL context I guess I should
make a new question about a new issue.

While I have transferred context from a main thread to a new rendering
thread, events don’t seem to be generated to the end application
properly.

What I do is a while(1) with pump events on the main thread.

Then I attempt - in 1.3 - to peep events from the secondary thread
with SDL_PeepEvents(sdl_events, MAX_EVENTS_PEEPED, SDL_GETEVENT,
SDL_USEREVENT, SDL_LASTEVENT); (in another while(1))

though it doesn’t return any events.

What might be wrong?

On Windows, events can only be gotten on the same thread that the window was created on. This is a system limitation.
I’m not sure about any other systems. The correct way to do this would be to get them on the main thread, and maybe pass them into your own thread-safe queue.------------------------
EM3 Nathaniel Fries, U.S. Navy

http://natefries.net/

Maybe we should create a FAQ item explaining people why most UI frameworks
are single threaded, and why they
should avoid threads everywhere.

Almost every month there is someone trying to do rendering or event handling
outside the main thread.–
Paulo

On Wed, Jan 19, 2011 at 12:44 PM, Nathaniel J Fries wrote:

On Windows, events can only be gotten on the same thread that the window
was created on. This is a system limitation.
I’m not sure about any other systems. The correct way to do this would be
to get them on the main thread, and maybe pass them into your own
thread-safe queue.


EM3 Nathaniel Fries, U.S. Navy

http://natefries.net/


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Yes, but SDL translates Windows events into SDL_Events, which are
placed in a thread safe event queue. I’m not sure why you would build
another system on top of this.

@ Michael Menegakis

A small demonstration program would be great, thanks. I’m suspicious
of your PeepEvents call, why are you only requesting SDL_UserEvents?
If you don’t regularly empty the event queue your UI will hang (at
least on Windows)…

Here is a test program I literally threw together. You can test the
threading and the peeping separately. I assume it won’t be too
difficult to convert to the SDL 1.3 API (which I don’t have installed
on this machine).

#include

#include “SDL.h”
#include “SDL_thread.h”

#define THREADS 1

template<typename T, int N>
int array_size(T (&array)[N]) {
return N;
}

void handleEvent(const SDL_Event &event, volatile bool &running) {
if(event.type == SDL_QUIT || (event.type == SDL_KEYDOWN &&
event.key.keysym.sym == SDLK_ESCAPE)) {
running = false;
} else {
std::cout << "Got event : " << (int)event.type << ‘\n’;
}
}

void usePeepEvents(volatile bool &running) {
SDL_Event events[100];
int result = SDL_PeepEvents(events, array_size(events),
SDL_GETEVENT, SDL_ALLEVENTS);
if(result < 0) {
std::cout << "Failed to peep events: " << SDL_GetError() << ‘\n’;
running = false;
} else {
for(int i = 0 ; i < result ; ++i) {
handleEvent(events[i], running);
}
}
}

volatile bool running = true;

int inputThread(void *) {
while(running) {
usePeepEvents(running);
SDL_Delay(10);
}
}

int main(int, char **)
{
#if defined(THREADS)
std::cout << “Events are threaded\n”;
#elif defined(PEEP)
std::cout << “Events are peeped\n”;
#else
std::cout << “Events are polled\n”;
#endif

if(SDL_Init(SDL_INIT_VIDEO) < 0) {
    std::cout << "Failed to init video: " << SDL_GetError() << '\n';
    return 1;
}
std::atexit(&SDL_Quit);

SDL_Surface *screen = SDL_SetVideoMode(800, 600, 0, 0);
if(!screen) {
    std::cout << "Failed to set video mode: " << SDL_GetError() << '\n';
    return 1;
}

#if defined(THREADS)
SDL_Thread *thread = SDL_CreateThread(&inputThread, 0);
if(!thread) {
std::cout << "Failed to create input thread: " <<
SDL_GetError() << ‘\n’;
}
#endif

while(running) {

#if defined(THREADS)
SDL_PumpEvents();
#elif defined(PEEP)
SDL_PumpEvents();
usePeepEvents(running);
#else
SDL_Event event;
while(SDL_PollEvent(&event)) {
handleEvent(event, running);
}
#endif
SDL_Delay(10);
SDL_FillRect(screen, 0, 0);
SDL_Flip(screen);
}
}

Something weird happened. I put SDL_PumpEvents() right before
SDL_PeepEvents() in the OpenGL window thread and it returned events
’normally’. But that doesn’t seem right since I read pump events can
only be called in the thread that set the video mode, and I understand
that means the SDL_Init() thread.

Unless… it meant the thread that brought up the window, since that
thread had to bring up a window and take the context with
SDL_GL_MakeCurrent().On Wed, Jan 19, 2011 at 5:30 PM, Brian Barrett <brian.ripoff at gmail.com> wrote:

Yes, but SDL translates Windows events into SDL_Events, which are
placed in a thread safe event queue. I’m not sure why you would build
another system on top of this.

Yes, I think so too.

Ah, wait a second, since SDL_SetVideoMode() appears removed in 1.3. I
guess it was correct to have pump events in the thread that runs the
OpenGL window since that thread had brought up its own window (which
is a kind of ‘video mode’) and then got the context for OpenGL from
the thread that run SDL init (which had released it with a
SDL_GL_MakeCurrent(window, NULL);).

Which means some of the advice in the mailing list is incorrect,
implying pump events must be done on the main SDL thread.

By the way, Brian Barrett, you were correct about my peeping events
being sketchy,

  • It had to have something like SDL_PeepEvents(sdl_events,
    MAX_EVENTS_PEEPED, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); (I
    guess)
  • SDL_Event had to be allocated normally and not just be a pointer
    (oops). Shouldn’t that be more clear in the docs by the way?

Though it wasn’t the reason of the overall bad behavior.On Wed, Jan 19, 2011 at 8:02 PM, Michael Menegakis <@Michael_Menegakis> wrote:

Something weird happened. I put SDL_PumpEvents() right before
SDL_PeepEvents() in the OpenGL window thread and it returned events
’normally’. But that doesn’t seem right since I read pump events can
only be called in the thread that set the video mode, and I understand
that means the SDL_Init() thread.

Unless… it meant the thread that brought up the window, since that
thread had to bring up a window and take the context with
SDL_GL_MakeCurrent().

On Wed, Jan 19, 2011 at 5:30 PM, Brian Barrett <brian.ripoff at gmail.com> wrote:

Yes, but SDL translates Windows events into SDL_Events, which are
placed in a thread safe event queue. I’m not sure why you would build
another system on top of this.

Yes, I think so too.

Can you give us a minimal example of what you are doing in your
program. Something not unlike my program in size?

SDL_Event had to be allocated normally and not just be a pointer
(oops). Shouldn’t that be more clear in the docs by the way?
Maybe it should be emphasised, but this is pretty normal behaviour for
a C API to pass a preallocated buffer and the buffer size to a
function and expect it filled. There is no way for the function to
pass information back, that would require a double pointer.

An example would have cleared up this misconception I imagine.

I currently mysteriously don’t get mousewheel events and the quit
event if I close the window. Any idea why? It does give mouse motion,
keyboard, and mouse keys properly. PollEvents did give them all
properly.

bool SDL_Events(void) {

SDL_Event sdl_events[MAX_EVENTS_PEEPED]; // This has to be allocated

normally, not be just a pointer.
int8_t events_peeped, i;

events_peeped = SDL_PeepEvents(sdl_events, MAX_EVENTS_PEEPED,

SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);

if (events_peeped == -1) {
	Print ("SDL_PeepEvents error: %s\n", SDL_GetError());
	return false;
}

for (i = 0 ; i < events_peeped; i++){ //do-while would need

preventing sdl_event being uninitialized

	if (sdl_events[i].type == SDL_MOUSEMOTION) {
		mouse_x += sdl_events[i].motion.xrel;
		mouse_y += sdl_events[i].motion.yrel;
	}

	if(sdl_events[i].type == SDL_MOUSEBUTTONDOWN /*|| sdl_event.type ==

SDL_MOUSEBUTTONUP*/){
switch( sdl_events[i].button.button ) {
case SDL_BUTTON_LEFT: if(wireframe) wireframe = false; else
wireframe = true; break;
case SDL_BUTTON_MIDDLE: if(multisampling) multisampling =
false; else multisampling = true; break;
case SDL_BUTTON_RIGHT: if(blending) blending = false; else
blending = true; break;
case SDL_BUTTON_WHEELUP: wheel -=3; break;
case SDL_BUTTON_WHEELDOWN: wheel +=3; break;
case 6: /MOUSE4?/ break;
case 7: /MOUSE5?/ break;
}
}

	if (sdl_events[i].type == SDL_KEYDOWN) {
		if (sdl_events[i].key.keysym.sym == SDLK_q) strafe++;
		if (sdl_events[i].key.keysym.sym == SDLK_e) strafe--;

		if (sdl_events[i].key.keysym.sym == SDLK_1) lightX = lightX - (GLfloat)0.075;
		if (sdl_events[i].key.keysym.sym == SDLK_2) lightX = lightX + (GLfloat)0.075;
		if (sdl_events[i].key.keysym.sym == SDLK_3) lightY = lightY - (GLfloat)0.075;
		if (sdl_events[i].key.keysym.sym == SDLK_4) lightY = lightY + (GLfloat)0.075;
		if (sdl_events[i].key.keysym.sym == SDLK_5) lightZ = lightZ - (GLfloat)0.075;
		if (sdl_events[i].key.keysym.sym == SDLK_6) lightZ = lightZ + (GLfloat)0.075;
		if (sdl_events[i].key.keysym.sym == SDLK_7) shine = shine - 2;
		if (sdl_events[i].key.keysym.sym == SDLK_8) shine = shine + 2;


		if (sdl_events[i].key.keysym.sym == SDLK_ESCAPE ||

sdl_events[i].key.keysym.sym == SDLK_RETURN) { return true; break; }
}

	if (	sdl_events[i].type == SDL_QUIT ) { return true; break; }
}

return false;

}On Wed, Jan 19, 2011 at 9:22 PM, Brian Barrett <brian.ripoff at gmail.com> wrote:

Can you give us a minimal example of what you are doing in your
program. Something not unlike my program in size?

Ah, nevermind, since I use the video thread anyway, I guess I should
avoid pumpevents altogether and go with pollevents.On Wed, Jan 19, 2011 at 11:05 PM, Michael Menegakis <@Michael_Menegakis> wrote:

On Wed, Jan 19, 2011 at 9:22 PM, Brian Barrett <brian.ripoff at gmail.com> wrote:

Can you give us a minimal example of what you are doing in your
program. Something not unlike my program in size?

I currently mysteriously don’t get mousewheel events and the quit
event if I close the window. Any idea why? It does give mouse motion,
keyboard, and mouse keys properly. PollEvents did give them all
properly.

No wait, I could use peep events since it can be in a dedicated events
thread. Sorry for the double/triple post.On Wed, Jan 19, 2011 at 11:08 PM, Michael Menegakis <@Michael_Menegakis> wrote:

On Wed, Jan 19, 2011 at 11:05 PM, Michael Menegakis <@Michael_Menegakis> wrote:

On Wed, Jan 19, 2011 at 9:22 PM, Brian Barrett <brian.ripoff at gmail.com> wrote:

Can you give us a minimal example of what you are doing in your
program. Something not unlike my program in size?

I currently mysteriously don’t get mousewheel events and the quit
event if I close the window. Any idea why? It does give mouse motion,
keyboard, and mouse keys properly. PollEvents did give them all
properly.

Ah, nevermind, since I use the video thread anyway, I guess I should
avoid pumpevents altogether and go with pollevents.

I afraid I find your posts hard to follow. A lot of the information is
omitted, you are discussion implementation details of your application
that we don’t know anything about. We’re not psychic, you’ll have to
show us the code or describe in detail your application. Showing us
the code is easier, and less vulnerable to miscommunication and
misinterpretation.

For example, if you think you have a case where events aren’t being
delivered, write a small application (again: my earlier one is an
example of the size to aim for) that demonstrates this behaviour.
Otherwise, there might be unrelated bugs in your application
architecture that interfere with your reasoning. For example, you are
using an event thread but you appear not to be managing the
synchronisation of the variables you are writing to. This could cause
lots of undefined behaviour, and possibly explain why your code is not
reacting to particular event types.On 19 January 2011 21:14, Michael Menegakis wrote:

No wait, I could use peep events since it can be in a dedicated events
thread. Sorry for the double/triple post.

I know it’s incomplete, mutexes are needed. However, I find it hard to
follow that consistently only wheel and window quit isn’t caught
though of course not inconceivable.

I suspect an SDL bug with peepevents compared to pollevents. Though I
wouldn’t discount a windows bug since I see peepevents goes back to
native system functions.On Wed, Jan 19, 2011 at 11:20 PM, Brian Barrett <brian.ripoff at gmail.com> wrote:

you are
using an event thread but you appear not to be managing the
synchronisation of the variables you are writing to. This could cause
lots of undefined behaviour, and possibly explain why your code is not
reacting to particular event types.

SDL 1.3 doesn’t post quit events anymore. Look at the reference for window events, you’re looking for “if(event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE)”

As for mousewheel events, it has been a long-standing bug that only the left mouse button is supported on Windows. There’s been a patch available for quite awhile that’s just fine; but Sam’s been taking his time at using it.

The thread that creates the Window (SDL_CreateWindow or SDL_SetVideoMode) is the one that gets the events. In this case, it seems like that’s the thread you’re already using.

As for why you needed to use SDL_PumpEvents to use SDL_PeepEvents; that’s because the queue isn’t updated unless you call SDL_PumpEvents; which SDL_PeepEvents does not IIRC (SDL_PollEvents does; and is what you should be using). This isn’t a bug either; SDL_PeepEvents shouldn’t pump the event queue.------------------------
EM3 Nathaniel Fries, U.S. Navy

http://natefries.net/

If you cannot give us a minimal example demonstrating this behaviour,
then its going to be difficult to believe you’ve found a bug. Not
impossible, mind you, just difficult.

In any case, SDL_PollEvent() is implemented in terms of
SDL_PeepEvents(), so a bug in the latter would affect the former.On 19 January 2011 21:44, Michael Menegakis wrote:

I know it’s incomplete, mutexes are needed. However, I find it hard to
follow that consistently only wheel and window quit isn’t caught
though of course not inconceivable.

I suspect an SDL bug with peepevents compared to pollevents. Though I
wouldn’t discount a windows bug since I see peepevents goes back to
native system functions.

Verified:
SDL_PeekEvents does not call SDL_PumpEvents.
SDL_PollEvent calls SDL_WaitEventTimeout; which calls SDL_PumpEvents before SDL_PeekEvents (literally the very line before)

So the issue with SDL_PeekEvents not updating the queue with new events does not cause the same in SDL_PollEvent; regardless of whether or not you consider it to be a bug in SDL_PeekEvents (I prefer to think not)------------------------
EM3 Nathaniel Fries, U.S. Navy

http://natefries.net/

Could then Sam apply this patch to the repository?

Thanks.

With kind regards,

JosFrom: sdl-bounces@lists.libsdl.org [mailto:sdl-bounces at lists.libsdl.org] On
Behalf Of Nathaniel J Fries
Sent: woensdag 19 januari 2011 22:50
To: sdl at lists.libsdl.org
Subject: Re: [SDL] peeping events from a new thread

SDL 1.3 doesn’t post quit events anymore. Look at the reference for window
events, you’re looking for “if(event.type == SDL_WINDOWEVENT &&
event.window.event == SDL_WINDOWEVENT_CLOSE)”

As for mousewheel events, it has been a long-standing bug that only the left
mouse button is supported on Windows. There’s been a patch available for
quite awhile that’s just fine; but Sam’s been taking his time at using it.

The thread that creates the Window (SDL_CreateWindow or SDL_SetVideoMode) is
the one that gets the events. In this case, it seems like that’s the thread
you’re already using.

As for why you needed to use SDL_PumpEvents to use SDL_PeepEvents; that’s
because the queue isn’t updated unless you call SDL_PumpEvents; which
SDL_PeepEvents does not IIRC (SDL_PollEvents does; and is what you should be
using). This isn’t a bug either; SDL_PeepEvents shouldn’t pump the event
queue.


EM3 Nathaniel Fries, U.S. Navy

http://natefries.net/


No virus found in this message.
Checked by AVG - www.avg.com
Version: 10.0.1191 / Virus Database: 1435/3390 - Release Date: 01/19/11

Jos Kuijpers wrote:

Could then Sam apply this patch to the repository?
Thanks.

With kind regards,

Jos

He’s aware of it, and I’ve made sure because I went through the bugtracker for him and e-mailed him every bug that had a decent patch or I had any idea of what the problem may be caused by and/or how to fix it.

He says he’ll go through the list soon, so I guess we’ll need to wait.------------------------
EM3 Nathaniel Fries, U.S. Navy

http://natefries.net/

Ok, thanks. Then I will stop asking for it.

If I am allowed to ask something else without creating another mail:

How far is the implementation of EVENTTHREAD and on what platforms is it
supported? Any documentation?

I saw it in SDL.h: SDL_INIT_EVENTHREAD.From: sdl-bounces@lists.libsdl.org [mailto:sdl-bounces at lists.libsdl.org] On
Behalf Of Nathaniel J Fries
Sent: donderdag 20 januari 2011 0:47
To: sdl at lists.libsdl.org
Subject: Re: [SDL] peeping events from a new thread

Jos Kuijpers wrote:

Could then Sam apply this patch to the repository?
Thanks.

With kind regards,

Jos

He’s aware of it, and I’ve made sure because I went through the bugtracker
for him and e-mailed him every bug that had a decent patch or I had any idea
of what the problem may be caused by and/or how to fix it.

He says he’ll go through the list soon, so I guess we’ll need to wait.


EM3 Nathaniel Fries, U.S. Navy

http://natefries.net/


No virus found in this message.
Checked by AVG - www.avg.com
Version: 10.0.1191 / Virus Database: 1435/3390 - Release Date: 01/19/11

Jos Kuijpers wrote:

Ok, thanks. Then I will stop asking for it.

If I am allowed to ask something else without creating another mail:
How far is the implementation of EVENTTHREAD and on what platforms is it supported? Any documentation?
I saw it in SDL.h: SDL_INIT_EVENTHREAD.

Most platforms do not support it; and I recommend simply ignoring its existence.------------------------
EM3 Nathaniel Fries, U.S. Navy

http://natefries.net/

The idea is to use PeepEvents in a dedicated events thread and a
PumpEvents in the video thread. Otherwise, if that’s buggy, the same
behavior could I guess achieved with a PollEvents in the video thread
and a user defined copying.On Wed, Jan 19, 2011 at 11:49 PM, Nathaniel J Fries wrote:

SDL_PollEvents does; and is what you should be using