Page 1 of 1

Tried separate render thread: isWindowActive returns false?!

Posted: Tue Feb 26, 2008 9:25 pm
by muenalan
i came up with the idea to have irrlicht rendering and physics in separate threads. I use irrlicht for displaying custom physical simulations. As the physics solver is heavy, it always hangs when I integrated it into the main loop rendering.

My attempt to seperate it into thread (code below) failed with mysterious effect: the window is not painted when the main loop is in a separate thread.

In the code below, this block is never ender, as it seem that isWindowActive() is not returning true (for a mysterious reason?):

Code: Select all

      if (engine.device->isWindowActive())
	{
	  std::cout << "Painting window..." << std::endl;


The code uses boost threads (dont are about the custom class ..engine etc - its just wrappers to the main irrlicht classes).

<snip>

struct thread_irrlicht_render
{
public:
  irrlicht_engine_startup &engine;

  irrlicht_event_reactor &reactor;

  irrlicht_node_factory &game_object_create;

   thread_irrlicht_render(
			  irrlicht_engine_startup &engine_,
			  irrlicht_event_reactor &reactor_,			 
			  irrlicht_node_factory &game_object_create_
			  ) : 
     engine(engine_),
     reactor( reactor_ ),
     game_object_create( game_object_create_ )     
  { 
  }

  void operator()()
  {
    std::cout << "Render thread.." << std::endl;

  while( engine.device->run() )
    {
      std::cout << "Device run..." << engine.device << std::endl;

      if (engine.device->isWindowActive())
	{
	  std::cout << "Painting window..." << std::endl;
                }
     }
  }
};


int main()
{
<snip>

  thread_irrlicht_render thread_render(engine, reactor, game_object_create );

  boost::thread thread_render_attached(thread_render);

  thread_render_attached.join();

<snip>

}

Posted: Wed Feb 27, 2008 2:45 am
by vitek
Actually, it's not mysterious at all. Irrlicht isn't written to be used from threads.

If you really want to know why this one particular issue comes up, then keep reading. That answer isn't really a mystery either. If you look at the function CIrrlichtDeviceWin32::isWindowActive(), it calls GetActiveWindow() to get the active window. From the documentation for that function...
The GetActiveWindow function retrieves the window handle to the active window attached to the calling thread's message queue.
You created a new thread, and you are indirectly calling GetActiveWindow() from that thread. Your thread doesn't have a message queue, so you get back NULL. If, for some reason, your thread does have a message queue, that threads active window isn't the Irrlicht window. Simple, right? You might be able to use GetForegroundWindow() instead, or modify the sources to use GetForegroundWindow().

I think it would be simpler to leave Irrlicht in the main thread and put your physics into the second thread.

Also, in the future, please use the

Code: Select all

 tag provided by the post editor. It makes your code much easier to read.

Travis

Posted: Wed Feb 27, 2008 11:48 am
by rogerborg
And as we keep saying, multithreading is not just a case of creating a new thread and hoping for the best. You will experience contention over shared resources. At best, you'll get inconsistent behaviour that will be a pig to debug. At worst, you'll get crashes as resources are invalidated in one thread (perhaps under error conditions that only occur on your clients' setups) when another thread still thinks they're valid.

You will have to put mutexing on your shared resources. If you simply mutex a single copy of shared data, then you lose most of the benefits of multithreading. I blueskyed a possible buffered shared data solution here, but I don't know of anyone who has successfully implemented this.

Posted: Fri Feb 29, 2008 7:19 pm
by muenalan
Hey, I decided to use the physics stuff in a separate thread for the moment. And indeed it works very well.

Obviously everything is possible with irrlicht, even so you don't have canonical multithreaded support.

May be one day I will also use the GetForegroundWindow() hint.


Thanks a lot for the comments !