2009/2/17 Richard Frith-Macdonald
<richard@tiptree.demon.co.uk>
On 17 Feb 2009, at 20:36, Julien Isorce wrote:
Hi,
I can read in NSApplication's documentation that it must be called in the main thread.
I am in a case where there is an other main loop (in C) that I cannot managed.
The code I can access is an interface and its implementation that leads to a shared library loaded by the main application where there is this C main loop.
Well, in the implementation (that I have to make) threre is 3 functions.
One for initialization, one for deinitialization, and the last one is called periodically.
In the init function I create an NSWindow. Then this window has to be updated in the function called periodically.
In no cocoa env I usually create a thread in the init function. This thread runs the specific window main loop (X loop or gdi32 loop). And it works pretty good.
I want to do the same thing in a cocoa env. I mean, i would like to run the cocoa main loop in a thread created in the init function.
Even if I read that NSApplicationMain (or [NSApp run] ) must be called in the main thread, I tried to call it in a different thread.
But I am getting an acces violation in the main thread.
Then if a replace the [NSApp run] from the second thread, by a while an a sleep, I have an access violation in the main thread only I do not call [NSApp run] in the main thread.
(but I cannot call [NSApp run] in the main thread because the function must be called periodically, I must not block the main thread)
I am creating the thread with:
[NSThread detachNewThreadSelector: @selector(start:)
toTarget: [AppThread class]
withObject: nil];
(like I could see in the gnu step examples)
I am still on win32.
Any suggestion ?
I wouldn't do it that way round.
Why not create an object to manage the C event loop, and run that in a secondary thread.
eg.
@interface LoopHandler : NSObject
- (void) callback;
- (void) run;
@end
@implementation LoopHandler
static LoopHandler *instance = nil;
static void
periodicLoopCallback()
{
[instance performSelectorInMainThread: @selector(callback) withObject: nil waitUntilDone: YES];
}
- (void) callback
{
/* perform callback handling here.
* this will be executed in the main thread whenever the
* C loop in the secondary thread calls preiodicLoopCallback
*/
}
- (id) init
{
instance = self;
return self;
}
- (void) run
{
// initialise C loop and tell it to use the callback function periodically
// run the C loop
}
@end
Then you would call
[NSThread detachNewThreadSelector: @selector(run) toTarget: [LoopHandler new] withObject: nil];
in your application startup code, and have all the GNUstep stuff working normally
Hi,
First, thx for your detailed suggestion.
It was not easy to understand why your suggestion is (or is not) a solution to my problem.
I am sure it's because my description was not clear.
I think you understood that the periodic function must be called in the main thread.
Actually it's not an obligation and so the solution would be easier:
I mean, run the C loop in a second thread (and so the periodic function too).
Then start the second thread from the main thread and then call the blocking function: [NSApp run] in the main thread.
Unfortunately, I am in a case where I cannot manage the C main loop (I cannot configure it and I cannot start it).
I am implemting a plugin interface which lead to a shared library.
This library is loaded by the main program and I have not access to the code of this main program and so I cannot have access to the code
which runs the C main loop.
It's like the concept of plugins work in some cases. But I am sure my first description was a little bit confusing.
In other word I cannot see how the periodic function could be called in an other thread than the main one.
So I still have access to 3 functions, init, periodic func, and deinit. Each one is called in the main thread.
I have a NSWindow created in the init function.
What I need is to run the cocoa main loop ( [NSApp run] ) the handle messages of this window.
I cannot run it in one of those 3 functions ( init, periodic func, and deinit), because [NSApp run] is blocking. And I must not block
the C main loop.
So I do not know where I can run it, because it seems it's not possible to run it in an other thread than the main thread (according to the documentation).
(note it's possible with other gui API, like X and win32. I experimented it a lot of times and it works very well)
A work arround could be to run ONE iteration (not blocking so) of the cocoa main loop in the periodic funcition.
But first I do not know how to do that with cocoa, and second, it's not really recommended. Indeed, if the period ( of the periodic function) is about 5 seconds, then the NSWindow would not be reactive to user events.
I appreciated your suggestion and if you could tell me more I would be grateful.
Sincerely
Julien