1
Window / Request: Move EventLoop processing to background thread
« on: April 01, 2012, 01:32:00 pm »
Hi,
currently when dragging the window with the mouse, the game stops (with most common implementations, atleast under ms windows), as the main thread hangs in the event loop.
By moving the event loop processing to a background thread this can be fixed.
My suggestion is to make this part of sfml.
Imo it's surely not a feature, that the game freezes when the window is moved.
Here is a sample implementation with C#, which atm is missing a method to stop the background thread. This could be implemented with a WaitEvent method with a timeout and then the main thread calls Dispose, which makes the background thread terminate as soon as it returns from the WaitEvent method:
Note that for this to work the window must be created from a background thread.
That's the reason, why the constructor is private and a factory method is used to create.
If all this is implemented as part of sfml these ugly details can be hidden and fixed behind the same interface which was always used.
I think that many people find the default behaviour annoying.
With sfml thread classes and/or the new standard there should be a way to implement it in c++ as part of sfml.
Btw does this problem also occur on other OS'es than windows?
Another nice thing for the window class would be a method to make the window have focus (I think it's missing).
currently when dragging the window with the mouse, the game stops (with most common implementations, atleast under ms windows), as the main thread hangs in the event loop.
By moving the event loop processing to a background thread this can be fixed.
My suggestion is to make this part of sfml.
Imo it's surely not a feature, that the game freezes when the window is moved.
Here is a sample implementation with C#, which atm is missing a method to stop the background thread. This could be implemented with a WaitEvent method with a timeout and then the main thread calls Dispose, which makes the background thread terminate as soon as it returns from the WaitEvent method:
public class ThreadedEventLoopRenderWindow : RenderWindow
{
private ConcurrentQueue<Event> eventQueue = new ConcurrentQueue<Event>();
public static ThreadedEventLoopRenderWindow Create(VideoMode mode, string title, Styles style, ContextSettings settings)
{
ThreadedEventLoopRenderWindow result = null;
bool windowCreated = false;
//the window must be created from the background thread
Thread eventThread = new Thread(() =>
{
result = new ThreadedEventLoopRenderWindow(mode, title, style, settings);
windowCreated = true;
result.ProcessEvents();
});
eventThread.IsBackground = true;
eventThread.Start();
while (!windowCreated) ;
return result;
}
private ThreadedEventLoopRenderWindow(VideoMode mode, string title, Styles style, ContextSettings settings)
: base(mode, title, style, settings)
{
SetActive(false);
}
private void ProcessEvents()
{
while (true) //replace this with sthg like while(!interrupted) and use a WaitEvent call with timeout
{
Event evt;
bool ok = base.WaitEvent(out evt);
if (ok)
{
eventQueue.Enqueue(evt);
}
}
}
protected override bool PollEvent(out Event eventToFill)
{
return eventQueue.TryDequeue(out eventToFill);
}
}
{
private ConcurrentQueue<Event> eventQueue = new ConcurrentQueue<Event>();
public static ThreadedEventLoopRenderWindow Create(VideoMode mode, string title, Styles style, ContextSettings settings)
{
ThreadedEventLoopRenderWindow result = null;
bool windowCreated = false;
//the window must be created from the background thread
Thread eventThread = new Thread(() =>
{
result = new ThreadedEventLoopRenderWindow(mode, title, style, settings);
windowCreated = true;
result.ProcessEvents();
});
eventThread.IsBackground = true;
eventThread.Start();
while (!windowCreated) ;
return result;
}
private ThreadedEventLoopRenderWindow(VideoMode mode, string title, Styles style, ContextSettings settings)
: base(mode, title, style, settings)
{
SetActive(false);
}
private void ProcessEvents()
{
while (true) //replace this with sthg like while(!interrupted) and use a WaitEvent call with timeout
{
Event evt;
bool ok = base.WaitEvent(out evt);
if (ok)
{
eventQueue.Enqueue(evt);
}
}
}
protected override bool PollEvent(out Event eventToFill)
{
return eventQueue.TryDequeue(out eventToFill);
}
}
Note that for this to work the window must be created from a background thread.
That's the reason, why the constructor is private and a factory method is used to create.
If all this is implemented as part of sfml these ugly details can be hidden and fixed behind the same interface which was always used.
I think that many people find the default behaviour annoying.
With sfml thread classes and/or the new standard there should be a way to implement it in c++ as part of sfml.
Btw does this problem also occur on other OS'es than windows?
Another nice thing for the window class would be a method to make the window have focus (I think it's missing).