Thread event question

Hello,

I’m trying to use SDL for an application I am working on. I’m having some
problems with thread communication.

Basically, what I want to do is from the main thread start a child thread
and in that child thread handle user events. These user events can be
generated by the event handling code in my main thread.

I’ve tried using PollEvent in my main event loop and PeepEvents on my child
thread but never seem to see the child thread events.

E.g., (from memory)

int ChildThread(void * data)
{
while(!done)
{
int evt = PeepEvents(event, 10, SDL_PEEKEVENT, SDL_USEREVENT)
for (int x=0; x<evt;x++)
{
switch(event[x].type)
{
case SDL_USEREVENT:
–blah,blah,blah—
done = true;
break;
}
}
}
}

main()
{
//create thread
while (SDL_PollEvent(&event))
{
cout << “m evt” << endl;
switch (event.type)
{
case SDL_KEYDOWN:
switch (event.key.keysym.sym)
{
case SDLK_s:
cout << “stop” << endl;

            SDL_Event evt;
            evt.type = SDL_USEREVENT;
            evt.user.code=UE_STOP;
            SDL_PushEvent(&evt);
            break;
        default:
            break;
        }
        break;
    default:
        break;
    }
    SDL_Delay(1);
}

}

This may not be exactly what I did, I tried some many combinations of the
event functions my head hurts.

FYIW, I’m using SDL 1.1.7 under Linux.

Regards,
Joe Cotellese

I’ve tried using PollEvent in my main event loop and PeepEvents on my child
thread but never seem to see the child thread events.

It sounds right. Can you post a minimal working (broken?) example?

Thanks,
-Sam Lantinga, Lead Programmer, Loki Entertainment Software

Sam Lantinga wrote:

I’ve tried using PollEvent in my main event loop and PeepEvents on my
child thread but never seem to see the child thread events.

It sounds right. Can you post a minimal working (broken?) example?

Thanks,
-Sam Lantinga, Lead Programmer, Loki Entertainment Software

#include
#include
#include <SDL.h>
#include <SDL_thread.h>

const int UE_BASE=SDL_USEREVENT+100;
const int UE_MYEVENT=UE_BASE+2;

int ChildThread(void * unused)
{
bool done = false;
SDL_Event event[10];
while (!done)
{
//read from the message pump,
//when we get our message, exit
int evt = SDL_PeepEvents(event, 10, SDL_GETEVENT, SDL_USEREVENT );
for (int x=0; x<evt;x++)
{
cout << “peep:” <<evt << endl;
cout <<event[x].type << endl;
switch(event[x].type)
{
case SDL_USEREVENT:
switch (event[x].user.code)
{
case UE_MYEVENT:
cout << “ue” << endl;
done = true;
break;
default:
break;
}
break;
}
}
SDL_Delay(10);
}
cout << “Done” << endl;
}

int main()
{
try
{
//Initalize the video subsystem, getting a main surface
SDL_Init(SDL_INIT_VIDEO);
SDL_Surface * main_surface = SDL_SetVideoMode(640, 480, 24,
SDL_HWSURFACE|SDL_DOUBLEBUF);
if (!main_surface)
throw -1;

    SDL_Thread * p_thread = SDL_CreateThread (ChildThread, NULL);

    SDL_Event event;
    //start the message pump
    bool running=true;
    SDL_Event evt;
    evt.type = SDL_USEREVENT;
    evt.user.code=UE_MYEVENT;

    while (running)
    {
        while (SDL_PollEvent(&event))
        {
            cout << "m evt" << endl;
            switch (event.type)
            {
            case SDL_KEYDOWN:
                switch (event.key.keysym.sym)
                {
                case SDLK_q:
                    cout << "q" << endl;
                    running = false;
                    break;
                case SDLK_s:
                    cout << "stop" << endl;
                    if (SDL_PushEvent(&evt)<0)
                        cout<<"Can't push" << endl;
                    break;
                default:
                    break;
                }
                break;
            default:
                break;
            }
            SDL_Delay(10);
        }
    }
    SDL_KillThread(p_thread);
    SDL_FreeSurface(main_surface);
    SDL_Quit();
} //try
catch(...)
{
    cout << "Unhandled exception" << endl;
}

}

Basically, what I am seeing is the the main thread always runs and never
yields to the child thread. The child loop runs, I see this if I move the
cout before the (for) statement. However, PeepEvents always returns 0. Is
it possible that the the main thread is eating my user event?

Regards,
Joe Cotellese

Basically, what I am seeing is the the main thread always runs and never
yields to the child thread. The child loop runs, I see this if I move the
cout before the (for) statement. However, PeepEvents always returns 0. Is
it possible that the the main thread is eating my user event?

Yes, that is most likely what’s happening. Instead of using PollEvent,
use PeepEvent with a mask of every event except SDL_USEREVENT. Remember,
the SDL event queue is a thread-safe FIFO.

See ya!
-Sam Lantinga, Lead Programmer, Loki Entertainment Software

Sam Lantinga wrote:

Basically, what I am seeing is the the main thread always runs and never
yields to the child thread. The child loop runs, I see this if I move the
cout before the (for) statement. However, PeepEvents always returns 0. Is
it possible that the the main thread is eating my user event?

Yes, that is most likely what’s happening. Instead of using PollEvent,
use PeepEvent with a mask of every event except SDL_USEREVENT. Remember,
the SDL event queue is a thread-safe FIFO.

See ya!
-Sam Lantinga, Lead Programmer, Loki Entertainment Software

Thanks for your help Sam. I took your suggestion and it works like a charm.
I’ve attached some dirty code that now works. If anyone else has problems
they can see a working example here.

#include
#include
#include <SDL.h>
#include <SDL_thread.h>

const int UE_BASE=SDL_USEREVENT+1;
const int UE_MYEVENT=UE_BASE+2;

int ChildThread(void * unused)
{
bool done = false;
SDL_Event event[10];
while (!done)
{
//read from the message pump,
//when we get our message, exit
int evt = SDL_PeepEvents(event, 10, SDL_GETEVENT, 1<<SDL_USEREVENT);
for (int x=0; x<evt;x++)
{
cout << “peep:” <<evt << endl;
switch(event[x].type)
{
case SDL_USEREVENT:
switch (event[x].user.code)
{
case UE_MYEVENT:
cout << “ue” << endl;
break;
case UE_BASE+1:
done=1;
break;
default:
break;
}
break;
}
}
SDL_Delay(10);
}
cout << “Done” << endl;
}

int main()
{
try
{
//Initalize the video subsystem, getting a main surface
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_EVENTTHREAD);
SDL_Surface * main_surface = SDL_SetVideoMode(640, 480, 24,
SDL_HWSURFACE|SDL_DOUBLEBUF);
if (!main_surface)
throw -1;

    SDL_Thread * p_thread = SDL_CreateThread (ChildThread, NULL);

    SDL_Event event[10];
    //start the message pump
    bool running=true;
    int ne;
    Uint32 mask = (SDL_KEYDOWNMASK|SDL_KEYUPMASK);
    SDL_Event evt;
    while (running)
    {
        SDL_PumpEvents();
        ne=SDL_PeepEvents(event, 10, SDL_GETEVENT, mask);
        for (int x=0; x<ne;x++)
        {
            switch (event[x].type)
            {
            case SDL_KEYDOWN:
                switch (event[x].key.keysym.sym)
                {
                case SDLK_q:
                    evt.type = SDL_USEREVENT;
                    evt.user.code=UE_BASE+1;
                    if (SDL_PushEvent(&evt)<0)
                        cout << "Error" << endl;

                    running = false;
                    break;
                case SDLK_s:
                    evt.type = SDL_USEREVENT;
                    evt.user.code=UE_MYEVENT;
                    if (SDL_PushEvent(&evt)<0)
                        cout << "Error" << endl;
                    break;
                default:
                    break;
                }
                break;
            default:
                break;
            }
            SDL_Delay(10);
        }
    }
    SDL_WaitThread(p_thread, NULL);
    SDL_FreeSurface(main_surface);
    SDL_Quit();
} //try
catch(...)
{
    cout << "Unhandled exception" << endl;
}

}

Joe Cotellese writes:

Hello,

I’m trying to use SDL for an application I am working on. I’m having some
problems with thread communication.

Basically, what I want to do is from the main thread start a child thread
and in that child thread handle user events. These user events can be
generated by the event handling code in my main thread.

I’ve tried using PollEvent in my main event loop and PeepEvents on my child
thread but never seem to see the child thread events.

I had a similar problem. If you look at the source for
SDL_PollEvent(), you’ll see that it simply calls SDL_PumpEvents() and
then calls SDL_PeepEvents() with appropriate flags. User events don’t
seem to get generated (or aren’t available to SDL_PeepEvents()) until
a call to SDL_PumpEvents(). So just prior to your call to
SDL_PeepEvents(), insert a call to SDL_PumpEvents().

One caveat: I had to put an initial call to SDL_PumpEvents() outside
(just prior to) my main event loop because I was getting one spurious
event from SDL_PeepEvents() if I didn’t do that. I haven’t yet
tracked down why it was necessary.

Derrell

Thanks for your help Sam. I took your suggestion and it works like a charm.
I’ve attached some dirty code that now works. If anyone else has problems
they can see a working example here.

You should grab all other messages in the main loop though, otherwise
an unexpected event type (like mouse motion) may fill up the event queue.

See ya!
-Sam Lantinga, Lead Programmer, Loki Entertainment Software