LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/cppuhelper/source - weak.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 164 189 86.8 %
Date: 2013-07-09 Functions: 36 40 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <osl/mutex.hxx>
      21             : #include <cppuhelper/weakagg.hxx>
      22             : #include <cppuhelper/interfacecontainer.hxx>
      23             : #include "cppuhelper/exc_hlp.hxx"
      24             : 
      25             : using namespace osl;
      26             : using namespace com::sun::star::uno;
      27             : 
      28             : /** */ //for docpp
      29             : namespace cppu
      30             : {
      31             : 
      32             : // due to static Reflection destruction from usr, ther must be a mutex leak (#73272#)
      33    20659516 : inline static Mutex & getWeakMutex() SAL_THROW(())
      34             : {
      35             :     static Mutex * s_pMutex = 0;
      36    20659516 :     if (! s_pMutex)
      37         384 :         s_pMutex = new Mutex();
      38    20659516 :     return *s_pMutex;
      39             : }
      40             : 
      41             : //------------------------------------------------------------------------
      42             : //-- OWeakConnectionPoint ----------------------------------------------------
      43             : //------------------------------------------------------------------------
      44             : class OWeakConnectionPoint : public XAdapter
      45             : {
      46             : public:
      47             :     /**
      48             :         Hold the weak object without an acquire (only the pointer).
      49             :      */
      50      215381 :     OWeakConnectionPoint( OWeakObject* pObj ) SAL_THROW(())
      51             :         : m_aRefCount( 0 )
      52             :         , m_pObject(pObj)
      53      215381 :         , m_aReferences( getWeakMutex() )
      54      215381 :         {}
      55             : 
      56             :     // XInterface
      57             :     Any SAL_CALL        queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException);
      58             :     void SAL_CALL       acquire() throw();
      59             :     void SAL_CALL       release() throw();
      60             : 
      61             :     // XAdapter
      62             :     ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL queryAdapted() throw(::com::sun::star::uno::RuntimeException);
      63             :     void SAL_CALL addReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException);
      64             :     void SAL_CALL removeReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException);
      65             : 
      66             :     /// Called from the weak object if the reference count goes to zero.
      67             :     void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
      68             : 
      69             : private:
      70             :     OWeakConnectionPoint(OWeakConnectionPoint &); // not defined
      71             :     void operator =(OWeakConnectionPoint &); // not defined
      72             : 
      73      427252 :     virtual ~OWeakConnectionPoint() {}
      74             : 
      75             :     /// The reference counter.
      76             :     oslInterlockedCount         m_aRefCount;
      77             :     /// The weak object
      78             :     OWeakObject*                m_pObject;
      79             :     /// The container to hold the weak references
      80             :     OInterfaceContainerHelper   m_aReferences;
      81             : };
      82             : 
      83             : // XInterface
      84           0 : Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType )
      85             :     throw(com::sun::star::uno::RuntimeException)
      86             : {
      87             :     return ::cppu::queryInterface(
      88           0 :         rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) );
      89             : }
      90             : 
      91             : // XInterface
      92     3489611 : void SAL_CALL OWeakConnectionPoint::acquire() throw()
      93             : {
      94     3489611 :     osl_atomic_increment( &m_aRefCount );
      95     3489611 : }
      96             : 
      97             : // XInterface
      98     3485816 : void SAL_CALL OWeakConnectionPoint::release() throw()
      99             : {
     100     3485816 :     if (! osl_atomic_decrement( &m_aRefCount ))
     101      213626 :         delete this;
     102     3485816 : }
     103             : 
     104      213626 : void SAL_CALL OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException)
     105             : {
     106      213626 :     Any ex;
     107      427252 :     OInterfaceIteratorHelper aIt( m_aReferences );
     108      620251 :     while( aIt.hasMoreElements() )
     109             :     {
     110             :         try
     111             :         {
     112      192999 :             ((XReference *)aIt.next())->dispose();
     113             :         }
     114           0 :         catch (com::sun::star::lang::DisposedException &) {}
     115           0 :         catch (RuntimeException &)
     116             :         {
     117           0 :             ex = cppu::getCaughtException();
     118             :         }
     119             :     }
     120      213626 :     if (ex.hasValue())
     121             :     {
     122           0 :         cppu::throwException(ex);
     123      213626 :     }
     124      213626 : }
     125             : 
     126             : // XInterface
     127     1967209 : Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException)
     128             : {
     129     1967209 :     Reference< XInterface > ret;
     130             : 
     131     3934418 :     ClearableMutexGuard guard(getWeakMutex());
     132             : 
     133     1967209 :     if (m_pObject)
     134             :     {
     135     1967209 :         oslInterlockedCount n = osl_atomic_increment( &m_pObject->m_refCount );
     136             : 
     137     1967209 :         if (n > 1)
     138             :         {
     139             :             // The refence is incremented. The object cannot be destroyed.
     140             :             // Release the guard at the earliest point.
     141     1953505 :             guard.clear();
     142             :             // WeakObject has a (XInterface *) cast operator
     143     1953505 :             ret = *m_pObject;
     144     1953505 :             n = osl_atomic_decrement( &m_pObject->m_refCount );
     145             :         }
     146             :         else
     147             :             // Another thread wait in the dispose method at the guard
     148       13704 :             n = osl_atomic_decrement( &m_pObject->m_refCount );
     149             :     }
     150             : 
     151     3934418 :     return ret;
     152             : }
     153             : 
     154             : // XInterface
     155      557012 : void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef)
     156             :     throw(::com::sun::star::uno::RuntimeException)
     157             : {
     158      557012 :     m_aReferences.addInterface( (const Reference< XInterface > &)rRef );
     159      557012 : }
     160             : 
     161             : // XInterface
     162      554971 : void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef)
     163             :     throw(::com::sun::star::uno::RuntimeException)
     164             : {
     165      554971 :     m_aReferences.removeInterface( (const Reference< XInterface > &)rRef );
     166      554971 : }
     167             : 
     168             : 
     169             : //------------------------------------------------------------------------
     170             : //-- OWeakObject -------------------------------------------------------
     171             : //------------------------------------------------------------------------
     172             : 
     173             : #ifdef _MSC_VER
     174             : // Accidentally occurs in msvc mapfile = > had to be outlined.
     175             : OWeakObject::OWeakObject() SAL_THROW(())
     176             :     : m_refCount( 0 ),
     177             :       m_pWeakConnectionPoint( 0 )
     178             : {
     179             : }
     180             : #endif
     181             : 
     182             : // XInterface
     183     3046481 : Any SAL_CALL OWeakObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
     184             : {
     185             :     return ::cppu::queryInterface(
     186             :         rType,
     187     3046481 :         static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
     188             : }
     189             : 
     190             : // XInterface
     191    94724745 : void SAL_CALL OWeakObject::acquire() throw()
     192             : {
     193    94724745 :     osl_atomic_increment( &m_refCount );
     194    94724745 : }
     195             : 
     196             : // XInterface
     197    83355432 : void SAL_CALL OWeakObject::release() throw()
     198             : {
     199    83355432 :     if (osl_atomic_decrement( &m_refCount ) == 0) {
     200             :         // notify/clear all weak-refs before object's dtor is executed
     201             :         // (which may check weak-refs to this object):
     202     7915878 :         disposeWeakConnectionPoint();
     203             :         // destroy object:
     204     7915878 :         delete this;
     205             :     }
     206    83355432 : }
     207             : 
     208     8404386 : void OWeakObject::disposeWeakConnectionPoint()
     209             : {
     210             :     OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" );
     211     8404386 :     if (m_pWeakConnectionPoint != 0) {
     212      213626 :         OWeakConnectionPoint * const p = m_pWeakConnectionPoint;
     213      213626 :         m_pWeakConnectionPoint = 0;
     214             :         try {
     215      213626 :             p->dispose();
     216             :         }
     217           0 :         catch (RuntimeException const& exc) {
     218             :             OSL_FAIL(
     219             :                 OUStringToOString(
     220             :                     exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
     221             :             static_cast<void>(exc);
     222             :         }
     223      213626 :         p->release();
     224             :     }
     225     8404386 : }
     226             : 
     227     8015405 : OWeakObject::~OWeakObject() SAL_THROW( (RuntimeException) )
     228             : {
     229     8015405 : }
     230             : 
     231             : // XWeak
     232      557012 : Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter()
     233             :     throw (::com::sun::star::uno::RuntimeException)
     234             : {
     235      557012 :     if (!m_pWeakConnectionPoint)
     236             :     {
     237             :         // only acquire mutex if member is not created
     238      215381 :         MutexGuard aGuard( getWeakMutex() );
     239      215381 :         if( !m_pWeakConnectionPoint )
     240             :         {
     241      215381 :             OWeakConnectionPoint * p = new OWeakConnectionPoint(this);
     242      215381 :             p->acquire();
     243      215381 :             m_pWeakConnectionPoint = p;
     244      215381 :         }
     245             :     }
     246             : 
     247      557012 :     return m_pWeakConnectionPoint;
     248             : }
     249             : 
     250             : //------------------------------------------------------------------------
     251             : //-- OWeakAggObject ----------------------------------------------------
     252             : //------------------------------------------------------------------------
     253      214380 : OWeakAggObject::~OWeakAggObject() SAL_THROW( (RuntimeException) )
     254             : {
     255      214380 : }
     256             : 
     257             : // XInterface
     258     6433201 : void OWeakAggObject::acquire() throw()
     259             : {
     260     6433201 :     Reference<XInterface > x( xDelegator );
     261     6433201 :     if (x.is())
     262      283552 :         x->acquire();
     263             :     else
     264     6149649 :         OWeakObject::acquire();
     265     6433201 : }
     266             : 
     267             : // XInterface
     268     6098319 : void OWeakAggObject::release() throw()
     269             : {
     270     6098319 :     Reference<XInterface > x( xDelegator );
     271     6098319 :     if (x.is())
     272      283323 :         x->release();
     273             :     else
     274     5814996 :         OWeakObject::release();
     275     6098319 : }
     276             : 
     277             : // XInterface
     278     1659264 : Any OWeakAggObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
     279             : {
     280     1659264 :     Reference< XInterface > x( xDelegator ); // harden ref
     281     1659264 :     return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType ));
     282             : }
     283             : 
     284             : // XAggregation
     285      882512 : Any OWeakAggObject::queryAggregation( const Type & rType ) throw(::com::sun::star::uno::RuntimeException)
     286             : {
     287             :     return ::cppu::queryInterface(
     288             :         rType,
     289             :         static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
     290             :         static_cast< XAggregation * >( this ),
     291      882512 :         static_cast< XWeak * >( this ) );
     292             : }
     293             : 
     294             : // XAggregation
     295        9143 : void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator ) throw(::com::sun::star::uno::RuntimeException)
     296             : {
     297        9143 :     xDelegator = rDelegator;
     298        9143 : }
     299             : 
     300             : }
     301             : 
     302             : /** */ //for docpp
     303             : namespace com
     304             : {
     305             : /** */ //for docpp
     306             : namespace sun
     307             : {
     308             : /** */ //for docpp
     309             : namespace star
     310             : {
     311             : /** */ //for docpp
     312             : namespace uno
     313             : {
     314             : 
     315             : 
     316             : //------------------------------------------------------------------------
     317             : //-- OWeakRefListener -----------------------------------------------------
     318             : //------------------------------------------------------------------------
     319             : class OWeakRefListener : public XReference
     320             : {
     321             : public:
     322             :     OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW(());
     323             :     OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW(());
     324             :     virtual ~OWeakRefListener() SAL_THROW(());
     325             : 
     326             :     // XInterface
     327             :     Any SAL_CALL queryInterface( const Type & rType ) throw(RuntimeException);
     328             :     void SAL_CALL acquire() throw();
     329             :     void SAL_CALL release() throw();
     330             : 
     331             :     // XReference
     332             :     void SAL_CALL   dispose() throw(::com::sun::star::uno::RuntimeException);
     333             : 
     334             :     /// The reference counter.
     335             :     oslInterlockedCount         m_aRefCount;
     336             :     /// The connection point of the weak object
     337             :     Reference< XAdapter >       m_XWeakConnectionPoint;
     338             : 
     339             : private:
     340             :     OWeakRefListener& SAL_CALL operator=(const OWeakRefListener& rRef) SAL_THROW(());
     341             : };
     342             : 
     343           0 : OWeakRefListener::OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW(())
     344             :     : com::sun::star::uno::XReference()
     345           0 :     , m_aRefCount( 1 )
     346             : {
     347             :     try
     348             :     {
     349           0 :     m_XWeakConnectionPoint = rRef.m_XWeakConnectionPoint;
     350             : 
     351           0 :     if (m_XWeakConnectionPoint.is())
     352             :     {
     353           0 :         m_XWeakConnectionPoint->addReference((XReference*)this);
     354             :     }
     355             :     }
     356           0 :     catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
     357           0 :     osl_atomic_decrement( &m_aRefCount );
     358           0 : }
     359             : 
     360      557012 : OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW(())
     361      557012 :     : m_aRefCount( 1 )
     362             : {
     363             :     try
     364             :     {
     365      557012 :     Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) );
     366             : 
     367      557012 :     if (xWeak.is())
     368             :     {
     369      557012 :         m_XWeakConnectionPoint = xWeak->queryAdapter();
     370             : 
     371      557012 :         if (m_XWeakConnectionPoint.is())
     372             :         {
     373      557012 :             m_XWeakConnectionPoint->addReference((XReference*)this);
     374             :         }
     375      557012 :     }
     376             :     }
     377           0 :     catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
     378      557012 :     osl_atomic_decrement( &m_aRefCount );
     379      557012 : }
     380             : 
     381     1662840 : OWeakRefListener::~OWeakRefListener() SAL_THROW(())
     382             : {
     383             :     try
     384             :     {
     385      554280 :     if (m_XWeakConnectionPoint.is())
     386             :     {
     387           0 :         acquire(); // dont die again
     388           0 :         m_XWeakConnectionPoint->removeReference((XReference*)this);
     389             :     }
     390             :     }
     391           0 :     catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
     392     1108560 : }
     393             : 
     394             : // XInterface
     395           0 : Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType ) throw(RuntimeException)
     396             : {
     397             :     return ::cppu::queryInterface(
     398           0 :         rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) );
     399             : }
     400             : 
     401             : // XInterface
     402     3871986 : void SAL_CALL OWeakRefListener::acquire() throw()
     403             : {
     404     3871986 :     osl_atomic_increment( &m_aRefCount );
     405     3871986 : }
     406             : 
     407             : // XInterface
     408     3867212 : void SAL_CALL OWeakRefListener::release() throw()
     409             : {
     410     3867212 :     if( ! osl_atomic_decrement( &m_aRefCount ) )
     411      554280 :         delete this;
     412     3867212 : }
     413             : 
     414      192999 : void SAL_CALL OWeakRefListener::dispose()
     415             :     throw(::com::sun::star::uno::RuntimeException)
     416             : {
     417      192999 :     Reference< XAdapter > xAdp;
     418             :     {
     419      192999 :         MutexGuard guard(cppu::getWeakMutex());
     420      192999 :         if( m_XWeakConnectionPoint.is() )
     421             :         {
     422      192999 :             xAdp = m_XWeakConnectionPoint;
     423      192999 :             m_XWeakConnectionPoint.clear();
     424      192999 :         }
     425             :     }
     426             : 
     427      192999 :     if( xAdp.is() )
     428      192999 :         xAdp->removeReference((XReference*)this);
     429      192999 : }
     430             : 
     431             : //------------------------------------------------------------------------
     432             : //-- WeakReferenceHelper ----------------------------------------------------------
     433             : //------------------------------------------------------------------------
     434      111052 : WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt) SAL_THROW(())
     435      111052 :     : m_pImpl( 0 )
     436             : {
     437      111052 :     if (xInt.is())
     438             :     {
     439      109844 :         m_pImpl = new OWeakRefListener(xInt);
     440      109844 :         m_pImpl->acquire();
     441             :     }
     442      111052 : }
     443             : 
     444      303731 : WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef) SAL_THROW(())
     445      303731 :     : m_pImpl( 0 )
     446             : {
     447      303731 :     Reference< XInterface > xInt( rWeakRef.get() );
     448      303731 :     if (xInt.is())
     449             :     {
     450      261422 :         m_pImpl = new OWeakRefListener(xInt);
     451      261422 :         m_pImpl->acquire();
     452      303731 :     }
     453      303731 : }
     454             : 
     455     1261029 : void WeakReferenceHelper::clear() SAL_THROW(())
     456             : {
     457             :     try
     458             :     {
     459     1261029 :         if (m_pImpl)
     460             :         {
     461      554280 :             if (m_pImpl->m_XWeakConnectionPoint.is())
     462             :             {
     463      361972 :                 m_pImpl->m_XWeakConnectionPoint->removeReference(
     464      361972 :                         (XReference*)m_pImpl);
     465      361972 :                 m_pImpl->m_XWeakConnectionPoint.clear();
     466             :             }
     467      554280 :             m_pImpl->release();
     468      554280 :             m_pImpl = 0;
     469             :         }
     470             :     }
     471           0 :     catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
     472     1261029 : }
     473             : 
     474        9475 : WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef) SAL_THROW(())
     475             : {
     476        9475 :     if (this == &rWeakRef)
     477             :     {
     478           0 :         return *this;
     479             :     }
     480        9475 :     Reference< XInterface > xInt( rWeakRef.get() );
     481        9475 :     return operator = ( xInt );
     482             : }
     483             : 
     484             : WeakReferenceHelper & SAL_CALL
     485      215636 : WeakReferenceHelper::operator= (const Reference< XInterface > & xInt)
     486             : SAL_THROW(())
     487             : {
     488             :     try
     489             :     {
     490      215636 :         clear();
     491      215636 :         if (xInt.is())
     492             :         {
     493      185746 :             m_pImpl = new OWeakRefListener(xInt);
     494      185746 :             m_pImpl->acquire();
     495             :         }
     496             :     }
     497           0 :     catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
     498      215636 :     return *this;
     499             : }
     500             : 
     501     1041978 : WeakReferenceHelper::~WeakReferenceHelper() SAL_THROW(())
     502             : {
     503     1041978 :     clear();
     504     1041978 : }
     505             : 
     506    18068545 : Reference< XInterface > WeakReferenceHelper::get() const SAL_THROW(())
     507             : {
     508             :     try
     509             :     {
     510    18068545 :     Reference< XAdapter > xAdp;
     511             :     {
     512    18068548 :         MutexGuard guard(cppu::getWeakMutex());
     513    18068548 :         if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() )
     514     1967209 :             xAdp = m_pImpl->m_XWeakConnectionPoint;
     515             :     }
     516             : 
     517    18068548 :     if (xAdp.is())
     518     1967209 :         return xAdp->queryAdapted();
     519             :     }
     520           0 :     catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected()
     521             : 
     522    16101339 :     return Reference< XInterface >();
     523             : }
     524             : 
     525             : }
     526             : }
     527             : }
     528             : }
     529             : 
     530             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10