void ZMessageLooperImpStd::ExitMessageLoop() { ZAssertLocked(1, fMutex_MessageDispatch); ZMutexLocker locker(fMutex_Structure); ZAssertStop(1, fRunMessageLoop); fRunMessageLoop = false; fCondition_Structure.Broadcast(); }
void ZWindow::InvalidateWindowMenuBar() { ZAssertLocked(kDebug_Window, this->GetLock()); if (!fPostedInvalidateMenuBar) { fPostedInvalidateMenuBar = true; ZMessage theMessage; theMessage.SetString("what", "zoolib:InvalidateMenuBar"); this->QueueMessage(theMessage); } }
ZMessageLooperImpStd::~ZMessageLooperImpStd() { ZAssertLocked(1, fMutex_MessageDispatch); if (sLooperForCurrentThread() == this) { /* If we're being called by ZMessageLooperImpStd::RunMessageLoop, potentially indirectly and from multiple nestings, then each caller of RunMessageLoop will have passed in the address of a bool, the last of which is now stored in fLooperExistsAddress. We set that false, and simply return from this method, which will return through each invoking RunMessageLoop, which will see that its bool is true, will set true the prior bool, and return without touching the this variable. In general, deleting ourselves is *not* a safe operation. ZooLib does so under very constrained circumstances, and you should also. However, sometime, somewhere, someone's going to PoseModal on some window, and then PoseModal on another window, and then delete the calling window before the calls to PoseModal have returned. And this all will handle that, although the rest of their code might not :) */ ZAssertStop(1, fLooperExistsAddress); *fLooperExistsAddress = false; fLooperExistsAddress = nil; } else { // In the other case we're being deleted by some other thread, and can thus just // force the main message loop to exit by setting fRunMessageLoop false, broadcasting // fCondition_Structure and waiting for fMessageLoopNesting to hit zero. fMutex_Structure.Acquire(); fRunMessageLoop = false; fCondition_Structure.Broadcast(); while (fMessageLoopNesting > 0) { fMutex_Structure.Release(); fCondition_MessageDispatch.Wait(fMutex_MessageDispatch); fMutex_Structure.Acquire(); } fMutex_Structure.Release(); } // The two branches above mean that ZMessageLooperImpStd is robust in the face // of destruction by calls from any source -- your own code may not be so // robust, so be careful how you trash message loopers. }
ZWindowWatcher::ZWindowWatcher(ZWindow* inWindow) : fWindow(inWindow) { fPrev = nil; fNext = nil; if (inWindow) { // You must hold the lock on a window at the time a watcher is created. You do not // have to do so when it goes out of scope (which is the whole point -- to be able // to know reliably when a window we *knew* about is still in existence) ZAssertLocked(kDebug_Window, inWindow->GetLock()); sMutex_WindowWatcher.Acquire(); fWindow = inWindow; fNext = fWindow->fWatcher_Head; if (fWindow->fWatcher_Head) fWindow->fWatcher_Head->fPrev = this; fWindow->fWatcher_Head = this; sMutex_WindowWatcher.Release(); } }