[mac-lisp-ide] runloops, threads, etc.

mikel evins mikel at evins.net
Thu Feb 5 22:00:45 UTC 2004


On Feb 5, 2004, at 1:47 PM, Gary Byers wrote:

> I just subscribed to this list a little while ago and wanted to respond
> to a few things that I saw in the archives.  I probably won't be able
> to attribute things too accurately, and I'm sure that I've missed
> parts of the discussion and may be replying to some things out of
> context.
>
> To the best of my knowledge, it's effectively the case that only one
> thread can fetch events from/communcate directly with the window
> server.  Prior to Panther, this was the thread whose CFRunloop was the
> "main" CFRunloop (there's still some code in OpenMCL's Cocoa demo that
> tries to play around with this, and it used to be the case that
> something called an undocumented function - something like
> "_CFRunLoopSetMain" - to try to get around this.  CF's "main" runloop
> ordinarily got created when CF was initialized, and it was associated
> with the thread that did that initialization.)
>
> Panther put an end to all this: the thread that's allowed to talk to
> the Window Server is the application's initial thread (the one
> that started out by calling main(), way back when) and none other.
> (Any other thread can certainly try to call NSApplication's
> nextEventMatchingMaskWhateverTheOtherArgsAre, but it'll get a NULL
> pointer back.)
>
> The basic model is that NSApplication's -run method loops around,
> getting events from the window server and propagating them through
> the responder chain.  From what I understand, lots of other things
> go on between the time that the -run method asks for an event and
> the time that it's delivered: raw window server events arrive;
> some of them are passed to Carbon event handlers (which might in
> some cases call Cocoa methods), some are related to keeping the
> window server's model of what's on screen in synch with the
> application's  (drawRect: methods get called at this time), etc.
> All of this is (by default) happening on the distinguished, blessed
> event thread.
>
> Some of the time of course, an NSEvent will eventually get returned
> to the caller.  Tim Moore and I tried some experiments about a year
> ago to see if we could intercept window-specific events and dispatch
> them to handlers that ran in window-specific threads (the thinking
> was that this was a lot closer to McCLIM's CLX backend's behavior.)
> The idea sort of worked (at least halfway). One way in which I
> remember it failing was when clicking on a window close button:
> the (blessed) event thread was waiting for the window-specific
> thread to unlock the view focus so it could ... do whatever it
> does, and the window-specific thread was waiting for a mouse-up
> event that never came.  It might have been possible to think
> a little harder and avoid this particular deadlock situation,
> but I got the strong impression that there were lots more deadlock
> situations waiting to happen.
>
> Apple had a Tech Note or similar document whose title was something
> like "AppKit is too thread-safe! Stop saying that it isn't !".  That
> document enumerated a small number of reasonable-sounding guidelines;
> I don't think that it's too hard to follow them carefully and still
> see totally unreasonable behavior.  I was trying a few months ago
> to build an NSTextView "manually" in some random (non-blessed) thread
> and it kept crashing; there could have been any number of reasons
> for that failure, but I eventually determined that as soon as I'd
> created an NSLayoutManager the blessed (if you'll pardon the 
> expression)
> thread decided that that'd be a good time to do background glyph
> layout.  (It wasn't ...).  I couldn't find a reliable way of preventing
> that from happening; in Cocoa's implicit view of the world, an
> NSTextView could only be constructed in the blessed event thread
> by some event handler (why on earth would a compute-bound thread
> want to create an NSTextView or an NSLayoutManager ?)  IIRC, I
> eventually wound up PROCESS-INTERRUPTing the event thread and
> asked it to make the NSTextView for me; that seemed to work fine.
>
> I'm not sure that I'm not just violently agreeing with points that
> other people have made; if people are thinking about bouncing events
> around between multiple lisp threads, I hope that they're aware of
> these issues and have thought of things that I'm missing.  The
> conclusion I came to is that Cocoa is really designed to have just
> about all of the interesting UI stuff happen in its blessed thread,
> and if any other approach is possible it may go so far against the
> grain as to be impractical.
>


This all agrees with my understanding, except that you know more about 
the details than I do. My embryonic McCLIM back-end builds a normal OSX 
application bundle and starts a blessed event loop in the normal way; 
my theory is that the event loop can hand events to windows and views 
in the normal-for-Cocoa way and the event handlers on the windows and 
views can trigger McCLIM functions, marshalling data as needed.

Duncan says he has some things sort of working by grabbing events 
himself, but it's possible he's living in the sort of twilight world 
that you describe above; I'm sure he'll weigh in on that.

He and I have been discussing a merge; if debugging event-handling is 
holding him up, and it turns out to be the same sort of problem you 
described, then it's possible that in the forthcoming merge he and I 
can fix things by switching to the Cocoa-event-loop-centric model.

--me





More information about the Mac-lisp-ide mailing list