[haiku-gsoc] Re: haiku-gsoc Digest V4 #22

  • From: Stephan Aßmus <superstippi@xxxxxx>
  • To: haiku-gsoc@xxxxxxxxxxxxx
  • Date: Tue, 28 Jun 2011 22:19:44 +0200

On 28.06.2011 19:55, Rene Gollent wrote:
On Tue, Jun 28, 2011 at 1:42 PM, Nathan Heisey<nathanheisey@xxxxxxxxx>  wrote:
Does this work the other way around, too?  I have a number of functions that
will be called from a driver object (presumably from the application thread,
although I'm not completely sure) corresponding to window actions (examples
are BE_Show/HideWindow and BE_MinimizeWindow).  So far I've just been
calling the BWindow functions directly.

They *can* be called from outside the window, but you'd have to ensure
that the window is locked first. Assuming you have control over when
the windows quit (i.e. if you implement Stephan's suggestion to
forward the window's quit requests to the app thread so the latter can
handle terminating the window), then it's reasonably safe to just use
window->Lock()/Unlock() pairs around the calls in question, otherwise
you would want to use a method like BMessenger's LockTarget() which
safely deals with the window object no longer existing.

When you only lock in one direction, for example always from the app thread and never from the window thread, then there is no problem. However, if you lock in both directions, you are asking for trouble in the form of "deadlocks". For example, in your window code you may try to grab the lock on the BApplication object before you invoke a method on it. This may block because the application thread is currently busy handling an event and has already grabbed the BApplication lock first. The event that the app thread handles in turn may run into code which tries to grab a lock on the BWindow object. This will block, because the window thread has the BWindow already locked. However, the window thread will not continue to run and never release that lock, since it is blocking for the application thread to release the BApplication lock. This situation is called a deadlock, since both threads are now blocking waiting for each other to release the respective other lock. Such a situation can happen when multiple locks are involved, and when the order in which threads grab these locks is undefined. When you always use messaging consistently, like in my examples, you completely avoid these headaches. On top of what Rene said, you can also safely invoke someBWindowPointer->PostMessage(), even if someBWindowPointer is stale and points to an already freed BWindow. This is some behind the scenes magic happening in PostMessage(), which prevents dereferencing stale BLooper pointers by means of looking it up in a list of valid BLoopers first. But let's not get distracted. If you stick to messaging like in my example code, you don't need to worry about anything special with regards to multi-threading.

Later you may have to apply some tricks, though, to make certain operations perform well, especially bringing whatever was rendered by SDL to the screen in a timely manner. We cross that bridge when we get there. :-)

Best regards,
-Stephan


Other related posts: