Am 23.01.2014 um 10:49 schrieb Sze Howe Koh <szehowe....@gmail.com>:

> On 23 January 2014 17:11, Till Oliver Knoll <till.oliver.kn...@gmail.com> 
> wrote:
>> However "GUI thread" is a more correct term, since - AFAIK - the instance of
>> QApplication does not necessarily have to "live" in the "main thread": ...
> 
> This is true on Windows, Linux, and Carbon Mac.
> 
> But unless I've grossly misunderstood something, this is not true on
> Cocoa Mac: 
> http://stackoverflow.com/questions/9761953/running-a-cocoa-gui-in-a-non-main-thread

Hmmm, bummer!
 
I did a quick google research and there are indeed discussions and blog entries 
– besides the one on Stack Overflow you posted – which really suggest that the 
NSApplication instance must live in the “main thread”, that is, really the 
thread where the main() entry function lives in.
 
Then there are other documents such as
 
   https://github.com/mpv-player/mpv/wiki/Cocoa-Constraints
 
which seem to confirm that, but make use of the words “is supposed to” (“Most 
of Cocoa UI, Event loop and Application classes are NOT thread safe and are 
/supposed to/ run in the main thread of the application”) and even suggest that 
it is possible to still instantiate NSApplication in a different thread 
(“Moving them out the main thread requires opening a connection to the window 
server manually: that is something in his right mind no one would do since it 
would be brittle and maintenance hell.”).
 
(Disclaimer for the following: I am not an experienced Cocoa developer - I use 
Qt for that ;))
 
However, I did not find any evidence in the Apple documents so far which would 
indicate that it is technically forbidden to instantiate an NSApplication (and 
call its “run method”) in a different thread than where the function main() 
lives in.
 
For instance:
 
 
https://developer.apple.com/library/mac/documentation/cocoa/reference/applicationkit/classes/NSApplication_Class/Reference/Reference.html
 
The “Overview” mentions that “Your program’s main() function should create this 
instance [of NSApplication] by invoking thesharedApplication class method.” – 
again the word “should” instead of “must”. And the following “The 
sharedApplication class method initializes the display environment and connects 
your program to the window server and the display server.” implies that it is 
really NSApplication:sharedApplication method which does the connection to the 
window manager, and not some Apple voodoo magic code which is run before the 
main() function (and which would hence technicaly /require/ that NSApplication 
be instantiated only in the thread where main() lives).
 
In fact, I believe that when the Apple documents talk about the “main thread” 
they really mean
 
  “The main thread is the one blocked in the run method of NSApplication, 
usually invoked in an application’s main function.”
 
See chapter “Event Handling Restrictions”
 
 
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html#//apple_ref/doc/uid/10000057i-CH12-123351-BBCFIIEB
 
“The thread being blocked in the run method of NSApplication” is, by that 
definition, not necessarily “the thread where function main() lives in”. And 
here again the word “usually” which implies “not always”.
 
 
So when put all the above together, in theory it should be possible to create 
an instance of NSThread in function main(), and within that thread create the 
shared instance of NSApplication (as described in the Apple NSApplication 
“Overview” documentation given above) and call its run method (the equivalent 
of QApplication::exec()). That newly created thread would then become the “main 
thread”, as soon as “run” is executing and processing all events, given my 
understanding of Apple’s definition of “main thread”. The method 
NSThread:isMainThread could also be helpful.
 
 
To bring this all a bit on-topic again: I did not know that creating a QThread 
is not possible without an instance of QApplication, but if the OP is willing 
to write some platform-specific code (which is easy: use “ObjC++” *.mm files as 
to mix ObjC with C++ and add those sources with OBJECTIVE_SOURCES += 
MyPlatformSpecificCode.mm to your project) the class NSThread could be used to 
spawn a new thread.
 
Then within that thread QApplication would be instantiated which eventually 
would instantiate NSApplication, and assuming that this NSApplication instance 
would have not been created previously (or after) already somewhere in main() 
(by some other code that the OP is executing before or after the thread 
creation) then that should work – again, in theory anyway ;)
 
 
If that fails, it would then be possible to “outsource” the whole GUI thread 
into its own process, start that process (with QProcess or whatever class is 
available at that time in main()) and communicate between “the GUI process” and 
the “main process” with e.g. local sockets and a custom (binary/textual) 
protocol (e.g. “command argument” based – or use JSON or whatever XML 
“dialect/protocol”).
 
  http://qt-project.org/doc/qt-5.0/qtnetwork/qlocalsocket.html
 
Or polling “state variables/messages” in shared memory:
 
  http://qt-project.org/doc/qt-5.0/qtcore/qsharedmemory.html
 
 
I once tried to implement “bi-directional communication” between parent-child 
processes with
 
  http://qt-project.org/doc/qt-5.0/qtcore/qprocess.html
 
alone, via stdin/stdout. That would be very nice, since you can treat a 
QProcess like a QIODevice and nicely read and write from/to it – in theory. But 
at least with Qt 4 I failed miserably at that time, and was told that 
“depending on the platform you’re totally lost and need platform-specific 
code”. I think especially on Windows that is a total PITA to get it right). But 
I can’t remember exactly what went wrong, write in one direction (probably 
child -> parent) did not work or the corresponding signals would not be emitted 
once data was available – anyway, I quickly gave up after some very convincing 
arguments here on qt-interest and am using local sockets now, which is much 
cleaner ;).
 
 
Cheers,
  Oliver
_______________________________________________
Interest mailing list
Interest@qt-project.org
http://lists.qt-project.org/mailman/listinfo/interest

Reply via email to