LCOV - code coverage report
Current view: top level - cppuhelper/source - weak.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 169 181 93.4 %
Date: 2015-06-13 12:38:46 Functions: 38 39 97.4 %
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 <sal/config.h>
      21             : 
      22             : #include <boost/noncopyable.hpp>
      23             : #include <osl/mutex.hxx>
      24             : #include <cppuhelper/weakagg.hxx>
      25             : #include <cppuhelper/interfacecontainer.hxx>
      26             : #include <cppuhelper/exc_hlp.hxx>
      27             : #include <cppuhelper/queryinterface.hxx>
      28             : 
      29             : using namespace osl;
      30             : using namespace com::sun::star::uno;
      31             : 
      32             : /** */ //for docpp
      33             : namespace cppu
      34             : {
      35             : 
      36             : // due to static Reflection destruction from usr, there must be a mutex leak (#73272#)
      37    72982857 : inline static Mutex & getWeakMutex()
      38             : {
      39             :     static Mutex * s_pMutex = 0;
      40    72982857 :     if (! s_pMutex)
      41         506 :         s_pMutex = new Mutex();
      42    72982857 :     return *s_pMutex;
      43             : }
      44             : 
      45             : 
      46             : //-- OWeakConnectionPoint ----------------------------------------------------
      47             : 
      48             : class OWeakConnectionPoint: public XAdapter, private boost::noncopyable
      49             : {
      50             : public:
      51             :     /**
      52             :         Hold the weak object without an acquire (only the pointer).
      53             :      */
      54     1750683 :     explicit OWeakConnectionPoint( OWeakObject* pObj )
      55             :         : m_aRefCount( 0 )
      56             :         , m_pObject(pObj)
      57     1750683 :         , m_aReferences( getWeakMutex() )
      58     1750683 :         {}
      59             : 
      60             :     // XInterface
      61             :     Any SAL_CALL        queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      62             :     void SAL_CALL       acquire() throw() SAL_OVERRIDE;
      63             :     void SAL_CALL       release() throw() SAL_OVERRIDE;
      64             : 
      65             :     // XAdapter
      66             :     ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL queryAdapted() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      67             :     void SAL_CALL addReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      68             :     void SAL_CALL removeReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      69             : 
      70             :     /// Called from the weak object if the reference count goes to zero.
      71             :     void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException);
      72             : 
      73             : private:
      74     3492536 :     virtual ~OWeakConnectionPoint() {}
      75             : 
      76             :     /// The reference counter.
      77             :     oslInterlockedCount         m_aRefCount;
      78             :     /// The weak object
      79             :     OWeakObject*                m_pObject;
      80             :     /// The container to hold the weak references
      81             :     OInterfaceContainerHelper   m_aReferences;
      82             : };
      83             : 
      84             : // XInterface
      85           9 : Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType )
      86             :     throw(com::sun::star::uno::RuntimeException, std::exception)
      87             : {
      88             :     return ::cppu::queryInterface(
      89           9 :         rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) );
      90             : }
      91             : 
      92             : // XInterface
      93    28969954 : void SAL_CALL OWeakConnectionPoint::acquire() throw()
      94             : {
      95    28969954 :     osl_atomic_increment( &m_aRefCount );
      96    28969954 : }
      97             : 
      98             : // XInterface
      99    28959246 : void SAL_CALL OWeakConnectionPoint::release() throw()
     100             : {
     101    28959246 :     if (! osl_atomic_decrement( &m_aRefCount ))
     102     1746268 :         delete this;
     103    28959246 : }
     104             : 
     105     1746268 : void SAL_CALL OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException)
     106             : {
     107     1746268 :     Any ex;
     108     3492536 :     OInterfaceIteratorHelper aIt( m_aReferences );
     109     5228053 :     while( aIt.hasMoreElements() )
     110             :     {
     111             :         try
     112             :         {
     113     1735517 :             static_cast<XReference *>(aIt.next())->dispose();
     114             :         }
     115           0 :         catch (com::sun::star::lang::DisposedException &) {}
     116           0 :         catch (RuntimeException &)
     117             :         {
     118           0 :             ex = cppu::getCaughtException();
     119             :         }
     120             :     }
     121     1746268 :     if (ex.hasValue())
     122             :     {
     123           0 :         cppu::throwException(ex);
     124     1746268 :     }
     125     1746268 : }
     126             : 
     127             : // XInterface
     128    12697493 : Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException, std::exception)
     129             : {
     130    12697493 :     Reference< XInterface > ret;
     131             : 
     132    25394986 :     ClearableMutexGuard guard(getWeakMutex());
     133             : 
     134    12697493 :     if (m_pObject)
     135             :     {
     136    12697493 :         oslInterlockedCount n = osl_atomic_increment( &m_pObject->m_refCount );
     137             : 
     138    12697493 :         if (n > 1)
     139             :         {
     140             :             // The refence is incremented. The object cannot be destroyed.
     141             :             // Release the guard at the earliest point.
     142    12611293 :             guard.clear();
     143             :             // WeakObject has a (XInterface *) cast operator
     144    12611293 :             ret = *m_pObject;
     145    12611293 :             n = osl_atomic_decrement( &m_pObject->m_refCount );
     146             :         }
     147             :         else
     148             :             // Another thread wait in the dispose method at the guard
     149       86200 :             n = osl_atomic_decrement( &m_pObject->m_refCount );
     150             :     }
     151             : 
     152    25394986 :     return ret;
     153             : }
     154             : 
     155             : // XInterface
     156     6393169 : void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef)
     157             :     throw(::com::sun::star::uno::RuntimeException, std::exception)
     158             : {
     159     6393169 :     m_aReferences.addInterface( (const Reference< XInterface > &)rRef );
     160     6393169 : }
     161             : 
     162             : // XInterface
     163     6386876 : void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef)
     164             :     throw(::com::sun::star::uno::RuntimeException, std::exception)
     165             : {
     166     6386876 :     m_aReferences.removeInterface( (const Reference< XInterface > &)rRef );
     167     6386876 : }
     168             : 
     169             : 
     170             : 
     171             : //-- OWeakObject -------------------------------------------------------
     172             : 
     173             : 
     174             : #ifdef _MSC_VER
     175             : // Accidentally occurs in msvc mapfile = > had to be outlined.
     176             : OWeakObject::OWeakObject()
     177             :     : m_refCount( 0 ),
     178             :       m_pWeakConnectionPoint( 0 )
     179             : {
     180             : }
     181             : #endif
     182             : 
     183             : // XInterface
     184   123475937 : Any SAL_CALL OWeakObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException, std::exception)
     185             : {
     186             :     return ::cppu::queryInterface(
     187             :         rType,
     188   123475937 :         static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) );
     189             : }
     190             : 
     191             : // XInterface
     192  7841085037 : void SAL_CALL OWeakObject::acquire() throw()
     193             : {
     194  7841085037 :     osl_atomic_increment( &m_refCount );
     195  7841085037 : }
     196             : 
     197             : // XInterface
     198  6428416677 : void SAL_CALL OWeakObject::release() throw()
     199             : {
     200  6428416677 :     if (osl_atomic_decrement( &m_refCount ) == 0) {
     201             :         // notify/clear all weak-refs before object's dtor is executed
     202             :         // (which may check weak-refs to this object):
     203   104043666 :         disposeWeakConnectionPoint();
     204             :         // destroy object:
     205   104043667 :         delete this;
     206             :     }
     207  6428416679 : }
     208             : 
     209   105264133 : void OWeakObject::disposeWeakConnectionPoint()
     210             : {
     211             :     OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" );
     212   105264133 :     if (m_pWeakConnectionPoint != 0) {
     213     1746268 :         OWeakConnectionPoint * const p = m_pWeakConnectionPoint;
     214     1746268 :         m_pWeakConnectionPoint = 0;
     215             :         try {
     216     1746268 :             p->dispose();
     217             :         }
     218           0 :         catch (RuntimeException const& exc) {
     219             :             OSL_FAIL(
     220             :                 OUStringToOString(
     221             :                     exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() );
     222             :             static_cast<void>(exc);
     223             :         }
     224     1746268 :         p->release();
     225             :     }
     226   105264133 : }
     227             : 
     228   104524741 : OWeakObject::~OWeakObject()
     229             : {
     230   104524737 : }
     231             : 
     232             : // XWeak
     233     6393169 : Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter()
     234             :     throw (::com::sun::star::uno::RuntimeException, std::exception)
     235             : {
     236     6393169 :     if (!m_pWeakConnectionPoint)
     237             :     {
     238             :         // only acquire mutex if member is not created
     239     1750683 :         MutexGuard aGuard( getWeakMutex() );
     240     1750683 :         if( !m_pWeakConnectionPoint )
     241             :         {
     242     1750683 :             OWeakConnectionPoint * p = new OWeakConnectionPoint(this);
     243     1750683 :             p->acquire();
     244     1750683 :             m_pWeakConnectionPoint = p;
     245     1750683 :         }
     246             :     }
     247             : 
     248     6393169 :     return m_pWeakConnectionPoint;
     249             : }
     250             : 
     251             : 
     252             : //-- OWeakAggObject ----------------------------------------------------
     253             : 
     254      449713 : OWeakAggObject::~OWeakAggObject()
     255             : {
     256      449713 : }
     257             : 
     258             : // XInterface
     259    18909425 : void OWeakAggObject::acquire() throw()
     260             : {
     261    18909425 :     Reference<XInterface > x( xDelegator );
     262    18909430 :     if (x.is())
     263     1356943 :         x->acquire();
     264             :     else
     265    17552487 :         OWeakObject::acquire();
     266    18909431 : }
     267             : 
     268             : // XInterface
     269    18506771 : void OWeakAggObject::release() throw()
     270             : {
     271    18506771 :     Reference<XInterface > x( xDelegator );
     272    18506776 :     if (x.is())
     273     1356751 :         x->release();
     274             :     else
     275    17150026 :         OWeakObject::release();
     276    18506778 : }
     277             : 
     278             : // XInterface
     279     3719069 : Any OWeakAggObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException, std::exception)
     280             : {
     281     3719069 :     Reference< XInterface > x( xDelegator ); // harden ref
     282     3719069 :     return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType ));
     283             : }
     284             : 
     285             : // XAggregation
     286     1879592 : Any OWeakAggObject::queryAggregation( const Type & rType ) throw(::com::sun::star::uno::RuntimeException, std::exception)
     287             : {
     288             :     return ::cppu::queryInterface(
     289             :         rType,
     290             :         static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ),
     291             :         static_cast< XAggregation * >( this ),
     292     1879592 :         static_cast< XWeak * >( this ) );
     293             : }
     294             : 
     295             : // XAggregation
     296       32830 : void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator ) throw(::com::sun::star::uno::RuntimeException, std::exception)
     297             : {
     298       32830 :     xDelegator = rDelegator;
     299       32830 : }
     300             : 
     301             : }
     302             : 
     303             : /** */ //for docpp
     304             : namespace com
     305             : {
     306             : /** */ //for docpp
     307             : namespace sun
     308             : {
     309             : /** */ //for docpp
     310             : namespace star
     311             : {
     312             : /** */ //for docpp
     313             : namespace uno
     314             : {
     315             : 
     316             : 
     317             : 
     318             : //-- OWeakRefListener -----------------------------------------------------
     319             : 
     320             : class OWeakRefListener: public XReference, private boost::noncopyable
     321             : {
     322             : public:
     323             :     explicit OWeakRefListener(const Reference< XInterface >& xInt);
     324             :     virtual ~OWeakRefListener();
     325             : 
     326             :     // XInterface
     327             :     Any SAL_CALL queryInterface( const Type & rType ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
     328             :     void SAL_CALL acquire() throw() SAL_OVERRIDE;
     329             :     void SAL_CALL release() throw() SAL_OVERRIDE;
     330             : 
     331             :     // XReference
     332             :     void SAL_CALL   dispose() throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     333             : 
     334             :     /// The reference counter.
     335             :     oslInterlockedCount         m_aRefCount;
     336             :     /// The connection point of the weak object
     337             :     Reference< XAdapter >       m_XWeakConnectionPoint;
     338             : };
     339             : 
     340     6393169 : OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt)
     341     6393169 :     : m_aRefCount( 1 )
     342             : {
     343             :     try
     344             :     {
     345     6393169 :     Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) );
     346             : 
     347     6393169 :     if (xWeak.is())
     348             :     {
     349     6393169 :         m_XWeakConnectionPoint = xWeak->queryAdapter();
     350             : 
     351     6393169 :         if (m_XWeakConnectionPoint.is())
     352             :         {
     353     6393169 :             m_XWeakConnectionPoint->addReference(static_cast<XReference*>(this));
     354             :         }
     355     6393169 :     }
     356             :     }
     357           0 :     catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
     358     6393169 :     osl_atomic_decrement( &m_aRefCount );
     359     6393169 : }
     360             : 
     361    19150752 : OWeakRefListener::~OWeakRefListener()
     362             : {
     363             :     try
     364             :     {
     365     6383584 :     if (m_XWeakConnectionPoint.is())
     366             :     {
     367           0 :         acquire(); // dont die again
     368           0 :         m_XWeakConnectionPoint->removeReference(static_cast<XReference*>(this));
     369             :     }
     370             :     }
     371           0 :     catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
     372    12767168 : }
     373             : 
     374             : // XInterface
     375          34 : Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
     376             : {
     377             :     return ::cppu::queryInterface(
     378          34 :         rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) );
     379             : }
     380             : 
     381             : // XInterface
     382    42027648 : void SAL_CALL OWeakRefListener::acquire() throw()
     383             : {
     384    42027648 :     osl_atomic_increment( &m_aRefCount );
     385    42027648 : }
     386             : 
     387             : // XInterface
     388    42011769 : void SAL_CALL OWeakRefListener::release() throw()
     389             : {
     390    42011769 :     if( ! osl_atomic_decrement( &m_aRefCount ) )
     391     6383584 :         delete this;
     392    42011769 : }
     393             : 
     394     1735517 : void SAL_CALL OWeakRefListener::dispose()
     395             :     throw(::com::sun::star::uno::RuntimeException, std::exception)
     396             : {
     397     1735517 :     Reference< XAdapter > xAdp;
     398             :     {
     399     1735517 :         MutexGuard guard(cppu::getWeakMutex());
     400     1735517 :         if( m_XWeakConnectionPoint.is() )
     401             :         {
     402     1735517 :             xAdp = m_XWeakConnectionPoint;
     403     1735517 :             m_XWeakConnectionPoint.clear();
     404     1735517 :         }
     405             :     }
     406             : 
     407     1735517 :     if( xAdp.is() )
     408     1735517 :         xAdp->removeReference(static_cast<XReference*>(this));
     409     1735517 : }
     410             : 
     411             : 
     412             : //-- WeakReferenceHelper ----------------------------------------------------------
     413             : 
     414     1504745 : WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt)
     415     1504745 :     : m_pImpl( 0 )
     416             : {
     417     1504745 :     if (xInt.is())
     418             :     {
     419     1502334 :         m_pImpl = new OWeakRefListener(xInt);
     420     1502334 :         m_pImpl->acquire();
     421             :     }
     422     1504745 : }
     423             : 
     424     4385157 : WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef)
     425     4385157 :     : m_pImpl( 0 )
     426             : {
     427     4385157 :     Reference< XInterface > xInt( rWeakRef.get() );
     428     4385157 :     if (xInt.is())
     429             :     {
     430     4280539 :         m_pImpl = new OWeakRefListener(xInt);
     431     4280539 :         m_pImpl->acquire();
     432     4385157 :     }
     433     4385157 : }
     434             : 
     435     8685765 : void WeakReferenceHelper::clear()
     436             : {
     437             :     try
     438             :     {
     439     8685765 :         if (m_pImpl)
     440             :         {
     441     6383584 :             if (m_pImpl->m_XWeakConnectionPoint.is())
     442             :             {
     443     4651359 :                 m_pImpl->m_XWeakConnectionPoint->removeReference(
     444     4651359 :                         static_cast<XReference*>(m_pImpl));
     445     4651359 :                 m_pImpl->m_XWeakConnectionPoint.clear();
     446             :             }
     447     6383584 :             m_pImpl->release();
     448     6383584 :             m_pImpl = 0;
     449             :         }
     450             :     }
     451           0 :     catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
     452     8685765 : }
     453             : 
     454       33292 : WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef)
     455             : {
     456       33292 :     if (this == &rWeakRef)
     457             :     {
     458           4 :         return *this;
     459             :     }
     460       33288 :     Reference< XInterface > xInt( rWeakRef.get() );
     461       33288 :     return operator = ( xInt );
     462             : }
     463             : 
     464             : WeakReferenceHelper & SAL_CALL
     465      717901 : WeakReferenceHelper::operator= (const Reference< XInterface > & xInt)
     466             : {
     467             :     try
     468             :     {
     469      717901 :         clear();
     470      717901 :         if (xInt.is())
     471             :         {
     472      610296 :             m_pImpl = new OWeakRefListener(xInt);
     473      610296 :             m_pImpl->acquire();
     474             :         }
     475             :     }
     476           0 :     catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
     477      717901 :     return *this;
     478             : }
     479             : 
     480     7957981 : WeakReferenceHelper::~WeakReferenceHelper()
     481             : {
     482     7957981 :     clear();
     483     7957981 : }
     484             : 
     485    55048509 : Reference< XInterface > WeakReferenceHelper::get() const
     486             : {
     487             :     try
     488             :     {
     489    55048509 :     Reference< XAdapter > xAdp;
     490             :     {
     491    55048496 :         MutexGuard guard(cppu::getWeakMutex());
     492    55048555 :         if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() )
     493    12697493 :             xAdp = m_pImpl->m_XWeakConnectionPoint;
     494             :     }
     495             : 
     496    55048541 :     if (xAdp.is())
     497    12697493 :         return xAdp->queryAdapted();
     498             :     }
     499           0 :     catch (RuntimeException &) { OSL_ASSERT( false ); } // assert here, but no unexpected()
     500             : 
     501    42351055 :     return Reference< XInterface >();
     502             : }
     503             : 
     504             : }
     505             : }
     506             : }
     507             : }
     508             : 
     509             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11