Tag: cws_src680_dba201b User: fs Date: 05/07/20 03:18:10 Modified: /dba/dbaccess/source/core/dataaccess/ databasedocument.cxx
Log: #i52171# better control over model ownership File Changes: Directory: /dba/dbaccess/source/core/dataaccess/ ================================================ File [changed]: databasedocument.cxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/core/dataaccess/databasedocument.cxx?r1=1.19.10.3&r2=1.19.10.4 Delta lines: +42 -53 --------------------- --- databasedocument.cxx 11 Jul 2005 13:37:00 -0000 1.19.10.3 +++ databasedocument.cxx 20 Jul 2005 10:18:08 -0000 1.19.10.4 @@ -2,9 +2,9 @@ * * $RCSfile: databasedocument.cxx,v $ * - * $Revision: 1.19.10.3 $ + * $Revision: 1.19.10.4 $ * - * last change: $Author: fs $ $Date: 2005/07/11 13:37:00 $ + * last change: $Author: fs $ $Date: 2005/07/20 10:18:08 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -393,41 +393,6 @@ m_pImpl->m_aControllers.erase(::std::find(m_pImpl->m_aControllers.begin(),m_pImpl->m_aControllers.end(),_xController)); if ( m_pImpl->m_xCurrentController == _xController ) m_pImpl->m_xCurrentController = NULL; - - // TODO: The below fragment is conceptually wrong. - // - // There are more clients of a database document (aka XModel) than its controllers. - // In particular, people might programmatically obtain a DataSource from the - // DatabaseContext, script it, and at some point obtain the document from - // the data source (XDocumentDataSource::getDatabaseDocument). All this might happen - // without any controller being involved, which means the document gets never disposed, - // which imlpies a resource leak. - // - // You might argue that the scripter who obtained the model is responsible for disposing - // it. However, she cannot know whether the model she just got from getDatabaseDocument - // is really hers (since it was newly created), or already owned by somebody else. So, - // she cannot know whether she is really allowed to dispose it. - // - // There is a pattern which could prevent this dilemma: closing with ownership delivery - // (XCloseable::close). With this pattern, every client of a component (here: the model) - // adds itself as XCloseListener to the component. When the client dies, it tries to - // close the component, with the DeliverOwnership parameter set to <TRUE/>. If there is - // another client of the component, it will veto the closing, and take the ownership - // (and in turn do an own close attempt later on). If there is no other client, closing - // will succeed. - // - // We should implement this for models, too. Then, controllers would be clients of the - // model, and do a close attempt when they disconnect. The model would never dispose - // itself (as it does now), but it would automatically be closed when the last client - // dies (provided that all clients respect this pattern). It turn, it would not be - // allowed to dispose a model directly. - // - // #i50905# / 2005-06-21 / [EMAIL PROTECTED] - if ( m_pImpl.is() && m_pImpl->m_aControllers.empty() ) - { - aGuard.clear(); - dispose(); - } } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::lockControllers( ) throw (RuntimeException) @@ -743,32 +708,50 @@ { } // ----------------------------------------------------------------------------- -void SAL_CALL ODatabaseDocument::close( sal_Bool bDeliverOwnership ) throw (::com::sun::star::util::CloseVetoException, RuntimeException) +void ODatabaseDocument::impl_closeControllerFrames( sal_Bool _bDeliverOwnership ) { - ResettableMutexGuard _rGuard(m_aMutex); - ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); - - lang::EventObject aEvt( static_cast< ::cppu::OWeakObject* >( this ) ); - NOTIFY_LISTERNERS1(m_aCloseListener,com::sun::star::util::XCloseListener,queryClosing,bDeliverOwnership); - ::std::vector< Reference< XController> > aCopy = m_pImpl->m_aControllers; + ::std::vector< Reference< XController> >::iterator aIter = aCopy.begin(); ::std::vector< Reference< XController> >::iterator aEnd = aCopy.end(); - for (;aIter != aEnd ; ++aIter) + for ( ;aIter != aEnd ; ++aIter ) { if ( aIter->is() ) { - Reference< XCloseable> xFrame((*aIter)->getFrame(),UNO_QUERY); + try + { + Reference< XCloseable> xFrame( (*aIter)->getFrame(), UNO_QUERY ); if ( xFrame.is() ) - xFrame->close(bDeliverOwnership); + xFrame->close( _bDeliverOwnership ); } + catch( const CloseVetoException& ) { throw; } + catch( const Exception& ) + { + OSL_ENSURE( sal_False, "ODatabaseDocument::impl_closeControllerFrames: caught an unexpected exception!" ); } - if ( m_pImpl.is() ) - m_pImpl->m_aControllers.clear(); - dispose(); + } + } +} + +// ----------------------------------------------------------------------------- +void SAL_CALL ODatabaseDocument::close( sal_Bool _bDeliverOwnership ) throw (::com::sun::star::util::CloseVetoException, RuntimeException) +{ + ResettableMutexGuard _rGuard(m_aMutex); + ::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed); + + lang::EventObject aEvt( static_cast< ::cppu::OWeakObject* >( this ) ); + { + NOTIFY_LISTERNERS1(m_aCloseListener,com::sun::star::util::XCloseListener,queryClosing,_bDeliverOwnership); + } + + DBG_ASSERT( m_pImpl->m_aControllers.empty(), "ODatabaseDocument::close: aren't controllers expected to veto the closing?" ); + impl_closeControllerFrames( _bDeliverOwnership ); + { NOTIFY_LISTERNERS(m_aCloseListener,com::sun::star::util::XCloseListener,notifyClosing); } + + dispose(); } // ----------------------------------------------------------------------------- void SAL_CALL ODatabaseDocument::addCloseListener( const Reference< ::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException) @@ -1099,6 +1082,12 @@ //------------------------------------------------------------------------------ void ODatabaseDocument::disposing() { + DBG_ASSERT( m_pImpl->m_aControllers.empty(), "ODatabaseDocument::disposing: there still are controllers!" ); + // normally, nobody should explicitly dispose, but only XCloseable::close the document. And controllers + // are expected to veto the closing, so when we're here, there shouldn't be any controllers anymore. + if ( m_pImpl.is() ) + m_pImpl->m_aControllers.clear(); + Reference< XModel > xHoldAlive( this ); { notifyEvent(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnUnload"))); --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
