Hi.
I am using boost.threads with SDL. Am using vc++2010.
I have wrapped the SDL input functions in a class SDL_Input.
eg.

class SDL_Input {
public:
bool* GetKeyState();
void ProcessEvents(){
static SDL_Event event;

    while(SDL_PollEvent(&event)) {
        switch(event.type) {
            case SDL_KEYDOWN:
                keystate[event.key.keysym.sym] = true;
                break;
//and all cases as mousebuttonup....so on
}
};

now in my program i tried using boost threads to run like :

SDL_Input in;
void Draw() {
in.ProcessEvents();
//other stuffs to manipulate the processed events
}

int _tmain(int argc, _TCHAR* argv[])
{
	boost::thread th(Draw);
	th.join();
	return 0;
}

Now when I run the program everything works fine but the input functions of the SDL.
Is there anything I have done wrong regarding use of boost.threads.
Or should I do sth else to use threads with sdl_events...
Input works well if i dont use threas;
Also other classes as SDL_Graphics(i have wrapped) work well.. even with the threads.
Input is creating all the trouble..
Need help plz...

Recommended Answers

All 5 Replies

AFAIK, SDL event polling can't be done in a thread other than the thread that set the video mode.

You could do something like this: The main thread (which set the video mode) polls for events and when an input event is received, it pushes it into (an appropriately synchronized) queue. The event handling thread runs a loop which waits on the queue, picks up events from it and then handles it.

Could you please demonstrate the concept roughly(as pseudo code), cause i cant get it clearly. Many many thanks..

To pass incoming data from one thread to another, the typical technique is:
1. The receiver of the data adds it to a queue shared between multiple threads.
2. The worker thread picks the data off the queue and processes it.

For this to work properly, the queue needs to be written so that data can safely be added by one thread and removed by another thread without corrupting the data structure. The standard way of doing this is by using a condition variable in conjunction with a mutex.

For a tutorial explaining this, see: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue-using-condition-variables.html

Here's a simple single-generator/single-consumer example (with random integer data generated in one thread and processed by another):

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/random.hpp>
#include <ctime>
#include <iostream>
#include <queue>

typedef boost::mutex::scoped_lock scoped_lock ;
typedef int event ;

struct event_queue_t
{
    bool empty() const
    {
        scoped_lock lock(mutex) ;
        return queue.empty() ;
    }

    const event& front() const
    {
        scoped_lock lock(mutex) ;
        return queue.front() ;
    }

    void push( const event& e )
    {
        scoped_lock lock(mutex) ;
        queue.push(e) ;
        condition.notify_one() ;
    }

    event pop()
    {
        scoped_lock lock(mutex) ;
        while( queue.empty() ) condition.wait(lock) ;
        event e = queue.front() ;
        queue.pop() ;
        return e ;
    }

    private :
        std::queue<event> queue ;
        mutable boost::mutex mutex ;
        boost::condition condition ;
} ;

event_queue_t event_queue ;
enum { N = 128 } ;
boost::mutex stdout_mutex ;

void event_generator()
{
    using namespace boost ;
    mt19937 twister( std::time(0) ) ;
    uniform_int<> distribution(0,999) ;
    variate_generator< mt19937&, uniform_int<> > gen( twister, distribution) ;

    for( int i = 0 ; i < N ; ++i )
    {
        event ev = gen() ;
        {
            scoped_lock lock(stdout_mutex) ;
            std::cout << "event_generator: pushing event " << ev << std::endl ;
        }
        event_queue.push(ev) ;
        system_time timeout = get_system_time() + posix_time::milliseconds(1) ;
        thread::sleep( timeout ) ;
    }
}

void event_handler()
{
    for( int i = 0 ; i < N ; ++i )
    {
        event ev = event_queue.pop() ;
        {
            scoped_lock lock(stdout_mutex) ;
            std::cout << "event_handler: handling event " << ev << std::endl ;
        }
    }
}

int main( )
{
      boost::thread event_generator_thread( &event_generator ) ;
      boost::thread event_handler_thread( &event_handler ) ;
      event_generator_thread.join() ;
      event_handler_thread.join() ;
}

Thanks for the post.
I read in the SDL Documentation the following:

Don't call SDL video/event functions from separate threads
Don't use any library functions in separate threads

Still some confusions left with SDL implementations:
1> As polling cant be done in thread other than main thread : i created two functions QueueEvents() and HandleEvents();
QueueEvents() simply polls for the events and pushes the events on a SDL_Event variable.
HandleEvents() checks the updated SDL_Event variable and operates.

class SDL_Input {
private:
SDL_Event event_type;//should it be static? but i will have just one object
}

Now as in main loop call QueueEvents() and before and outside created thread of HandleEvents() as:

bool *keystate = in.GetKeyState; //"in" is my object
event_handle = boost::thread(&SDL_Input::HandleEvents, in);
	while(!done)
	{
		in.QueueEvents();
		if(keystate[SDLK_ESCAPE]) done = true;
		if(in.QuitRequest()) done = true;

things are not still working. Could u please modify my above program, to implement your previous SG/SC example.

Thanks for the suggestions. I finally made it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.