FROM : Chris Kane
DATE : Sat Jan 12 19:37:01 2002
On Monday, January 7, 2002, at 08:00 PM, Steve Green wrote:
> Suppose a have a cocoa app happily doing it's thing, when via some user
> input, I need to spawn a thread to perform some lengthy calculation.
> The main app will return to it's event loop (NSRunLoop?) while spawned
> thread chugs away. When the calculation is complete, I need to signal
> the main app to collect the results, and clean up.
>
> It seems that there are multiple ways I could perform the notification,
> but it's not clear to me which will work, and be thread safe, etc..
>
> Thought 1: Start a timer with zero timeout in the main app thread.
> Seems like a hack, and I am not sure it's thread safe.
>
> Thought 2: NSRunLoop performSelector:target:argument:order:modes:.
> Will it work? What do I pass for modes:?
>
> Thought 3: NSApplication postEvent:atStart:. The documentation
> suggests this but it does not suggest what event to send or how to sign
> up to receive it. If it turns out that this is the best way to solve
> my problem, then I am sure I can figure that out the rest, but I
> imagine that there must be a simpler way. After all, maybe I am
> writing an app that does not use NSApplication.
>
> Thought 4: NSConnection. Seems like overkill?
>
> Thought 5: Use a unix pipe with the socket class (I forget the name).
> This didn't 'feel' like the right solution in this environment.
Here's another one I'll bet nobody has tried yet, and might or might not
work: wrap the Mach port for the background thread in a CFMachPort,
register an invalidation callback for it, and put it in the run loop of
the main thread. When the invalidation callback function is called, the
thread is done and the main thread can pick up its results from memory
(or wherever the thread has put them). This probably won't work,
because it depends on the pthreads library getting the Mach thread
object destroyed right away when the thread exits -- which is very
implementation dependent (the pthread might be cached for later reuse,
rather than destroyed, since it is "relatively expensive" to create
them, for example). This sort of thing is done by several bits of
software I know of for tasks, to watch for task death via the run loop;
tantalizing but probably impractical for threads.
#1 and #4 will work. #2 won't, since that won't schedule the work in
the main thread. #5 probably overkill as well. I don't think I'd risk
the thread-safety of #3.
If the Cocoa group would get off its collective butt and implement
-performSelectorInMainThread:blah:blah:blah:, you'd just use that. But
disagreements over semantics and behavior, and higher priority items,
always seem to get in the way.
This is an example of getting a thread to do some work. A
lighter-weight approach than DO is to use NSPortMessage, send a trivial
message to an NSPort in the main thread (previously registered, probably
before the thread was spawned off, to make sure it exists by the time
the thread dies). CFMessagePort can be used for the same, at the CF
level.
If you add a timer to the main thread's run loop (which presumably
you've squirreled away somewhere), be sure to use CFRunLoopWakeUp() on
the CFRunLoopRef of the NSRunLoop. Cocoa won't do that for you
currently (and it's not clear it should -- might degrade the performance
unnecessarily).
Finally, another solution is to create a little custom "version 0"
CFRunLoopSourceRef using the CF API, add that to the CFRunLoop (in the
main thread), then CFRunLoopSourceSignal() it in the side thread when
the thread is done (and CFRunLoopWakeUp()). The perform callback for
the source will be invoked in the main thread.
Chris Kane
Cocoa Frameworks, Apple
DATE : Sat Jan 12 19:37:01 2002
On Monday, January 7, 2002, at 08:00 PM, Steve Green wrote:
> Suppose a have a cocoa app happily doing it's thing, when via some user
> input, I need to spawn a thread to perform some lengthy calculation.
> The main app will return to it's event loop (NSRunLoop?) while spawned
> thread chugs away. When the calculation is complete, I need to signal
> the main app to collect the results, and clean up.
>
> It seems that there are multiple ways I could perform the notification,
> but it's not clear to me which will work, and be thread safe, etc..
>
> Thought 1: Start a timer with zero timeout in the main app thread.
> Seems like a hack, and I am not sure it's thread safe.
>
> Thought 2: NSRunLoop performSelector:target:argument:order:modes:.
> Will it work? What do I pass for modes:?
>
> Thought 3: NSApplication postEvent:atStart:. The documentation
> suggests this but it does not suggest what event to send or how to sign
> up to receive it. If it turns out that this is the best way to solve
> my problem, then I am sure I can figure that out the rest, but I
> imagine that there must be a simpler way. After all, maybe I am
> writing an app that does not use NSApplication.
>
> Thought 4: NSConnection. Seems like overkill?
>
> Thought 5: Use a unix pipe with the socket class (I forget the name).
> This didn't 'feel' like the right solution in this environment.
Here's another one I'll bet nobody has tried yet, and might or might not
work: wrap the Mach port for the background thread in a CFMachPort,
register an invalidation callback for it, and put it in the run loop of
the main thread. When the invalidation callback function is called, the
thread is done and the main thread can pick up its results from memory
(or wherever the thread has put them). This probably won't work,
because it depends on the pthreads library getting the Mach thread
object destroyed right away when the thread exits -- which is very
implementation dependent (the pthread might be cached for later reuse,
rather than destroyed, since it is "relatively expensive" to create
them, for example). This sort of thing is done by several bits of
software I know of for tasks, to watch for task death via the run loop;
tantalizing but probably impractical for threads.
#1 and #4 will work. #2 won't, since that won't schedule the work in
the main thread. #5 probably overkill as well. I don't think I'd risk
the thread-safety of #3.
If the Cocoa group would get off its collective butt and implement
-performSelectorInMainThread:blah:blah:blah:, you'd just use that. But
disagreements over semantics and behavior, and higher priority items,
always seem to get in the way.
This is an example of getting a thread to do some work. A
lighter-weight approach than DO is to use NSPortMessage, send a trivial
message to an NSPort in the main thread (previously registered, probably
before the thread was spawned off, to make sure it exists by the time
the thread dies). CFMessagePort can be used for the same, at the CF
level.
If you add a timer to the main thread's run loop (which presumably
you've squirreled away somewhere), be sure to use CFRunLoopWakeUp() on
the CFRunLoopRef of the NSRunLoop. Cocoa won't do that for you
currently (and it's not clear it should -- might degrade the performance
unnecessarily).
Finally, another solution is to create a little custom "version 0"
CFRunLoopSourceRef using the CF API, add that to the CFRunLoop (in the
main thread), then CFRunLoopSourceSignal() it in the side thread when
the thread is done (and CFRunLoopWakeUp()). The perform callback for
the source will be invoked in the main thread.
Chris Kane
Cocoa Frameworks, Apple
| Related mails | Author | Date |
|---|---|---|
| Steve Green | Jan 7, 20:00 | |
| Chris Kane | Jan 12, 19:37 | |
| Greg Titus | Jan 12, 20:50 | |
| Rainer Brockerhoff | Jan 13, 07:26 |






Cocoa mail archive

