Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [mac os x][sfml-1.6]Window from non-main-Thread  (Read 4300 times)

0 Members and 1 Guest are viewing this topic.

SimonTheVillain

  • Newbie
  • *
  • Posts: 1
    • View Profile
[mac os x][sfml-1.6]Window from non-main-Thread
« on: February 05, 2011, 09:36:54 am »
Like the title says, i have tried to use the window class from outside the main thread with great success on every system except on mac os x.
As soon as i create a window object in an other thread than main, i get a(i'm not mac user but they seem to call it that way) waterball of death and a window with a white tile bar.

My Software is written in a way that makes it difficult to change the window and OpenGL managing thread to the main thread. So doe's anybody know a solution?


Here a piece of code that should represent the problem and should cause the same problem as described:

Code: [Select]


#include <SFML/Window.hpp>



void threadProc(void* userData){
    // Create the main window
    sf::Window App(sf::VideoMode(800, 600, 32), "SFML Events");

    // Get a reference to the input manager associated to our window, and store it for later use
    const sf::Input& Input = App.GetInput();

    // Start main loop
    while (App.IsOpened())
    {
        // Process events
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                App.Close();

            // Escape key : exit
            if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
                App.Close();
        }

        // Display window on screen
        App.Display();
    }

}

int main()
{
sf::Thread Thread(threadProc);
Thread.Launch();
Thread.Wait();

    return EXIT_SUCCESS;
}


Hope i made it clear, although my english is on a very low level.  :D

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #1 on: February 05, 2011, 08:31:27 pm »
Because nothing has been done so that events can be retrieved from other threads. Thus you catch no event and you get a "waterball of death".

There is no way to fix your issue easily with the current SFML 1.x Mac OS X port. I don't know whether this is possible with the Mac port of SFML 2.

If you want to keep on using SFML 1, then you have no other way than handling the events in the main thread.
Want to play movies in your SFML application? Check out sfeMovie!

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #2 on: February 05, 2011, 08:45:57 pm »
I've done some research this afternoon about this because there is the same behaviour with SFML2, unfortunately.  :?

And I've some bad news. I found this post here : http://stackoverflow.com/questions/2060770/cocoa-windows-and-threads

Quote
Cocoa does have run loops per thread. But they are not used to process user events.


Which is pretty much confirmed by the official documentation here : http://developer.apple.com/library/mac .

Quote
The main thread of the application is responsible for handling events.


So it seems hard to make it work... But I'll take some more time to find if there is an acceptable workaround (maybe looking at GNUStep implementation).
SFML / OS X developer

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #3 on: February 06, 2011, 08:19:15 pm »
Maybe you could connect the run loop of the main thread to the run loop of the other thread. I've already read something like that (but I can't remember whether this exactly fits your needs).
Want to play movies in your SFML application? Check out sfeMovie!

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #4 on: February 06, 2011, 08:44:30 pm »
Well, currently I've no idea on how to do that, so if you have any clue please advise me.  :)
SFML / OS X developer

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
Want to play movies in your SFML application? Check out sfeMovie!

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #6 on: February 06, 2011, 08:59:24 pm »
thanks, I'll have a look!  :)
SFML / OS X developer

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #7 on: February 17, 2011, 12:39:55 am »
I've done some reading since last time. Ceylo, your link was interesting but I think it won't work because NSEvent are not NSNotification (which is supported by the documentation).

I've also found another problem with thread programming :
Quote
The NSView class is generally thread-safe, with a few exceptions. You should create, destroy, resize, move, and perform other operations on NSView objects only from the main thread of an application.


It means that only this multithread application structure is supported :
Code: [Select]
main thread :
create sfml window

launch thread (drawing stuff)

classic event loop without drawing


Once again the doc agree on this :
Quote
Threads and Your User Interface
If your application has a graphical user interface, it is recommended that you receive user-related events and initiate interface updates from your application’s main thread. This approach helps avoid synchronization issues associated with handling user events and drawing window content. Some frameworks, such as Cocoa, generally require this behavior, but even for those that do not, keeping this behavior on the main thread has the advantage of simplifying the logic for managing your user interface.


Now the problem is that this behaviour is not standard regarding SFML on Linux and Windows. (Isn't it?) And I don't have any solution. I still can ask on cocoa-dev mailing list for a confirmation of this behaviour but I really doubt the answer would be helpful.

What should I/we do ? Add something in the doc/tutorial in order to advice people who want to produce an app for Mac ?

Right now I'm kind of disappointed. Who would think that a major OS like OS X wouldn't allow us to do that ? :(

edit : typo
SFML / OS X developer

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #8 on: February 17, 2011, 01:36:14 am »
Well, you should still try to use the MachPort and checks whether it can be used to receive events. I'm not as positive as you.

And from what I understand, you cannot create/destroy/whatever from another thread. But you can still ask for the main thread to do that work for you, through -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:].

I agree it's quite odd, but that may work.
Want to play movies in your SFML application? Check out sfeMovie!

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #9 on: February 17, 2011, 08:58:56 am »
(a 'not' was missing in the 1st § in my previous message.)

Quote from: "Ceylo"
But you can still ask for the main thread to do that work for you, through -[NSObject performSelectorOnMainThread:withObject:waitUntilDone:].

In normal circumstances it would work but I cannot use this kind of method because : (here)
Quote
This method queues the message on the run loop of the main thread using the default run loop modes—that is, the modes associated with the NSRunLoopCommonModes constant. As part of its normal run loop processing, the main thread dequeues the message (assuming it is running in one of the default run loop modes) and invokes the desired method.
And as I'm not running the default NSApp run method it would require in the best case that the SFML user has at least one window in the main thread – or run periodically a special function which would change the SFML API which is not a good choice. Without that it won't be possible at all. So I can't use that.  :?
SFML / OS X developer

Ceylo

  • Hero Member
  • *****
  • Posts: 2325
    • View Profile
    • http://sfemovie.yalir.org/
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #10 on: February 17, 2011, 12:07:53 pm »
Hmmm.. ok. Looks like you're kinda stuck :? .
Want to play movies in your SFML application? Check out sfeMovie!

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #11 on: February 18, 2011, 10:09:54 am »
just to be sure I've posted to cocoa-dev mailing list. You can see the message here (but it hasn't been replied yet).
SFML / OS X developer

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
[mac os x][sfml-1.6]Window from non-main-Thread
« Reply #12 on: February 19, 2011, 11:52:32 am »
Bad news confirmed : http://lists.apple.com/archives/cocoa-dev/2011/Feb/msg00493.html

I have an idea that should solve the problem, but I don't like it – and I'm sure you won't too.

Code: [Select]
int myMain(int, char**) {
  // 'classic' main code goes here..
}

int main(int argc, char** argv) {
  return sf::Main(myMain, argc, argv);
}


Some arguments :
Pro
    -Qt, Cocoa, Wx and some other use that kind of main.
    -It (should) allows a really easy fix of the ATI graphics issue
    -It should fix thread on mac issue
    -On Linux/Win it shouldn't required much work

Contra
    -It's a very strong pattern (maybe too strong for some user/usage)
    -It changes the public API to fix a implementation issue (IMO, bad!)


--------------------------------------

An alternative is to keep this behaviour and have something like this
Quote
Threads and Your User Interface
If your application has a graphical user interface, it is recommended that you receive user-related events and initiate interface updates from your application’s main thread. This approach helps avoid synchronization issues associated with handling user events and drawing window content. Some frameworks, such as Cocoa, generally require this behavior, but even for those that do not, keeping this behavior on the main thread has the advantage of simplifying the logic for managing your user interface.
in the doc/tutorial with some warning for users that want to produce a OS X app.



What do you think ?
SFML / OS X developer

 

anything