1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_cppuhelper.hxx" 30 #include <osl/mutex.hxx> 31 #ifndef _CPPU_WEAKAGG_HXX_ 32 #include <cppuhelper/weakagg.hxx> 33 #endif 34 #ifndef _CPPU_HELPER_INTERFACECONTAINER_HXX_ 35 #include <cppuhelper/interfacecontainer.hxx> 36 #endif 37 #include "cppuhelper/exc_hlp.hxx" 38 39 using namespace osl; 40 using namespace com::sun::star::uno; 41 42 /** */ //for docpp 43 namespace cppu 44 { 45 46 // due to static Reflection destruction from usr, ther must be a mutex leak (#73272#) 47 inline static Mutex & getWeakMutex() SAL_THROW( () ) 48 { 49 static Mutex * s_pMutex = 0; 50 if (! s_pMutex) 51 s_pMutex = new Mutex(); 52 return *s_pMutex; 53 } 54 55 //------------------------------------------------------------------------ 56 //-- OWeakConnectionPoint ---------------------------------------------------- 57 //------------------------------------------------------------------------ 58 class OWeakConnectionPoint : public XAdapter 59 { 60 public: 61 /** 62 Hold the weak object without an acquire (only the pointer). 63 */ 64 OWeakConnectionPoint( OWeakObject* pObj ) SAL_THROW( () ) 65 : m_aRefCount( 0 ) 66 , m_pObject(pObj) 67 , m_aReferences( getWeakMutex() ) 68 {} 69 70 // XInterface 71 Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException); 72 void SAL_CALL acquire() throw(); 73 void SAL_CALL release() throw(); 74 75 // XAdapter 76 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL queryAdapted() throw(::com::sun::star::uno::RuntimeException); 77 void SAL_CALL addReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException); 78 void SAL_CALL removeReference( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XReference >& xRef ) throw(::com::sun::star::uno::RuntimeException); 79 80 /// Called from the weak object if the reference count goes to zero. 81 void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); 82 83 private: 84 OWeakConnectionPoint(OWeakConnectionPoint &); // not defined 85 void operator =(OWeakConnectionPoint &); // not defined 86 87 virtual ~OWeakConnectionPoint() {} 88 89 /// The reference counter. 90 oslInterlockedCount m_aRefCount; 91 /// The weak object 92 OWeakObject* m_pObject; 93 /// The container to hold the weak references 94 OInterfaceContainerHelper m_aReferences; 95 }; 96 97 // XInterface 98 Any SAL_CALL OWeakConnectionPoint::queryInterface( const Type & rType ) 99 throw(com::sun::star::uno::RuntimeException) 100 { 101 return ::cppu::queryInterface( 102 rType, static_cast< XAdapter * >( this ), static_cast< XInterface * >( this ) ); 103 } 104 105 // XInterface 106 void SAL_CALL OWeakConnectionPoint::acquire() throw() 107 { 108 osl_incrementInterlockedCount( &m_aRefCount ); 109 } 110 111 // XInterface 112 void SAL_CALL OWeakConnectionPoint::release() throw() 113 { 114 if (! osl_decrementInterlockedCount( &m_aRefCount )) 115 delete this; 116 } 117 118 void SAL_CALL OWeakConnectionPoint::dispose() throw(::com::sun::star::uno::RuntimeException) 119 { 120 Any ex; 121 OInterfaceIteratorHelper aIt( m_aReferences ); 122 while( aIt.hasMoreElements() ) 123 { 124 try 125 { 126 ((XReference *)aIt.next())->dispose(); 127 } 128 catch (com::sun::star::lang::DisposedException &) {} 129 catch (RuntimeException &) 130 { 131 ex = cppu::getCaughtException(); 132 } 133 } 134 if (ex.hasValue()) 135 { 136 cppu::throwException(ex); 137 } 138 } 139 140 // XInterface 141 Reference< XInterface > SAL_CALL OWeakConnectionPoint::queryAdapted() throw(::com::sun::star::uno::RuntimeException) 142 { 143 Reference< XInterface > ret; 144 145 ClearableMutexGuard guard(getWeakMutex()); 146 147 if (m_pObject) 148 { 149 oslInterlockedCount n = osl_incrementInterlockedCount( &m_pObject->m_refCount ); 150 151 if (n > 1) 152 { 153 // The refence is incremented. The object cannot be destroyed. 154 // Release the guard at the earliest point. 155 guard.clear(); 156 // WeakObject has a (XInterface *) cast operator 157 ret = *m_pObject; 158 n = osl_decrementInterlockedCount( &m_pObject->m_refCount ); 159 } 160 else 161 // Another thread wait in the dispose method at the guard 162 n = osl_decrementInterlockedCount( &m_pObject->m_refCount ); 163 } 164 165 return ret; 166 } 167 168 // XInterface 169 void SAL_CALL OWeakConnectionPoint::addReference(const Reference< XReference >& rRef) 170 throw(::com::sun::star::uno::RuntimeException) 171 { 172 m_aReferences.addInterface( (const Reference< XInterface > &)rRef ); 173 } 174 175 // XInterface 176 void SAL_CALL OWeakConnectionPoint::removeReference(const Reference< XReference >& rRef) 177 throw(::com::sun::star::uno::RuntimeException) 178 { 179 m_aReferences.removeInterface( (const Reference< XInterface > &)rRef ); 180 } 181 182 183 //------------------------------------------------------------------------ 184 //-- OWeakObject ------------------------------------------------------- 185 //------------------------------------------------------------------------ 186 187 #ifdef _MSC_VER 188 // Accidentally occurs in msvc mapfile = > had to be outlined. 189 OWeakObject::OWeakObject() SAL_THROW( () ) 190 : m_refCount( 0 ), 191 m_pWeakConnectionPoint( 0 ) 192 { 193 } 194 #endif 195 196 // XInterface 197 Any SAL_CALL OWeakObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException) 198 { 199 return ::cppu::queryInterface( 200 rType, 201 static_cast< XWeak * >( this ), static_cast< XInterface * >( this ) ); 202 } 203 204 // XInterface 205 void SAL_CALL OWeakObject::acquire() throw() 206 { 207 osl_incrementInterlockedCount( &m_refCount ); 208 } 209 210 // XInterface 211 void SAL_CALL OWeakObject::release() throw() 212 { 213 if (osl_decrementInterlockedCount( &m_refCount ) == 0) { 214 // notify/clear all weak-refs before object's dtor is executed 215 // (which may check weak-refs to this object): 216 disposeWeakConnectionPoint(); 217 // destroy object: 218 delete this; 219 } 220 } 221 222 void OWeakObject::disposeWeakConnectionPoint() 223 { 224 OSL_PRECOND( m_refCount == 0, "OWeakObject::disposeWeakConnectionPoint: only to be called with a ref count of 0!" ); 225 if (m_pWeakConnectionPoint != 0) { 226 OWeakConnectionPoint * const p = m_pWeakConnectionPoint; 227 m_pWeakConnectionPoint = 0; 228 try { 229 p->dispose(); 230 } 231 catch (RuntimeException const& exc) { 232 OSL_ENSURE( 233 false, OUStringToOString( 234 exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); 235 static_cast<void>(exc); 236 } 237 p->release(); 238 } 239 } 240 241 OWeakObject::~OWeakObject() SAL_THROW( (RuntimeException) ) 242 { 243 } 244 245 // XWeak 246 Reference< XAdapter > SAL_CALL OWeakObject::queryAdapter() 247 throw (::com::sun::star::uno::RuntimeException) 248 { 249 if (!m_pWeakConnectionPoint) 250 { 251 // only acquire mutex if member is not created 252 MutexGuard aGuard( getWeakMutex() ); 253 if( !m_pWeakConnectionPoint ) 254 { 255 OWeakConnectionPoint * p = new OWeakConnectionPoint(this); 256 p->acquire(); 257 m_pWeakConnectionPoint = p; 258 } 259 } 260 261 return m_pWeakConnectionPoint; 262 } 263 264 //------------------------------------------------------------------------ 265 //-- OWeakAggObject ---------------------------------------------------- 266 //------------------------------------------------------------------------ 267 OWeakAggObject::~OWeakAggObject() SAL_THROW( (RuntimeException) ) 268 { 269 } 270 271 // XInterface 272 void OWeakAggObject::acquire() throw() 273 { 274 Reference<XInterface > x( xDelegator ); 275 if (x.is()) 276 x->acquire(); 277 else 278 OWeakObject::acquire(); 279 } 280 281 // XInterface 282 void OWeakAggObject::release() throw() 283 { 284 Reference<XInterface > x( xDelegator ); 285 if (x.is()) 286 x->release(); 287 else 288 OWeakObject::release(); 289 } 290 291 // XInterface 292 Any OWeakAggObject::queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException) 293 { 294 Reference< XInterface > x( xDelegator ); // harden ref 295 return (x.is() ? x->queryInterface( rType ) : queryAggregation( rType )); 296 297 // // set rOut to zero, if failed 298 // if( !xDelegator.queryHardRef( aUik, rOut ) ) 299 // { 300 // XInterfaceRef x; 301 // if( !xDelegator.queryHardRef( ((XInterface*)0)->getSmartUik(), x ) ) 302 // // reference is not valid 303 // queryAggregation( aUik, rOut ); 304 // } 305 // return rOut.is(); 306 } 307 308 // XAggregation 309 Any OWeakAggObject::queryAggregation( const Type & rType ) throw(::com::sun::star::uno::RuntimeException) 310 { 311 return ::cppu::queryInterface( 312 rType, 313 static_cast< XInterface * >( static_cast< OWeakObject * >( this ) ), 314 static_cast< XAggregation * >( this ), 315 static_cast< XWeak * >( this ) ); 316 } 317 318 // XAggregation 319 void OWeakAggObject::setDelegator( const Reference<XInterface > & rDelegator ) throw(::com::sun::star::uno::RuntimeException) 320 { 321 xDelegator = rDelegator; 322 } 323 324 } 325 326 /** */ //for docpp 327 namespace com 328 { 329 /** */ //for docpp 330 namespace sun 331 { 332 /** */ //for docpp 333 namespace star 334 { 335 /** */ //for docpp 336 namespace uno 337 { 338 339 340 //------------------------------------------------------------------------ 341 //-- OWeakRefListener ----------------------------------------------------- 342 //------------------------------------------------------------------------ 343 class OWeakRefListener : public XReference 344 { 345 public: 346 OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW( () ); 347 OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW( () ); 348 virtual ~OWeakRefListener() SAL_THROW( () ); 349 350 // XInterface 351 Any SAL_CALL queryInterface( const Type & rType ) throw(RuntimeException); 352 void SAL_CALL acquire() throw(); 353 void SAL_CALL release() throw(); 354 355 // XReference 356 void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); 357 358 /// The reference counter. 359 oslInterlockedCount m_aRefCount; 360 /// The connection point of the weak object 361 Reference< XAdapter > m_XWeakConnectionPoint; 362 363 private: 364 OWeakRefListener& SAL_CALL operator=(const OWeakRefListener& rRef) SAL_THROW( () ); 365 }; 366 367 OWeakRefListener::OWeakRefListener(const OWeakRefListener& rRef) SAL_THROW( () ) 368 : com::sun::star::uno::XReference() 369 , m_aRefCount( 1 ) 370 { 371 try 372 { 373 m_XWeakConnectionPoint = rRef.m_XWeakConnectionPoint; 374 375 if (m_XWeakConnectionPoint.is()) 376 { 377 m_XWeakConnectionPoint->addReference((XReference*)this); 378 } 379 } 380 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected() 381 osl_decrementInterlockedCount( &m_aRefCount ); 382 } 383 384 OWeakRefListener::OWeakRefListener(const Reference< XInterface >& xInt) SAL_THROW( () ) 385 : m_aRefCount( 1 ) 386 { 387 try 388 { 389 Reference< XWeak > xWeak( Reference< XWeak >::query( xInt ) ); 390 391 if (xWeak.is()) 392 { 393 m_XWeakConnectionPoint = xWeak->queryAdapter(); 394 395 if (m_XWeakConnectionPoint.is()) 396 { 397 m_XWeakConnectionPoint->addReference((XReference*)this); 398 } 399 } 400 } 401 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected() 402 osl_decrementInterlockedCount( &m_aRefCount ); 403 } 404 405 OWeakRefListener::~OWeakRefListener() SAL_THROW( () ) 406 { 407 try 408 { 409 if (m_XWeakConnectionPoint.is()) 410 { 411 acquire(); // dont die again 412 m_XWeakConnectionPoint->removeReference((XReference*)this); 413 } 414 } 415 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected() 416 } 417 418 // XInterface 419 Any SAL_CALL OWeakRefListener::queryInterface( const Type & rType ) throw(RuntimeException) 420 { 421 return ::cppu::queryInterface( 422 rType, static_cast< XReference * >( this ), static_cast< XInterface * >( this ) ); 423 } 424 425 // XInterface 426 void SAL_CALL OWeakRefListener::acquire() throw() 427 { 428 osl_incrementInterlockedCount( &m_aRefCount ); 429 } 430 431 // XInterface 432 void SAL_CALL OWeakRefListener::release() throw() 433 { 434 if( ! osl_decrementInterlockedCount( &m_aRefCount ) ) 435 delete this; 436 } 437 438 void SAL_CALL OWeakRefListener::dispose() 439 throw(::com::sun::star::uno::RuntimeException) 440 { 441 Reference< XAdapter > xAdp; 442 { 443 MutexGuard guard(cppu::getWeakMutex()); 444 if( m_XWeakConnectionPoint.is() ) 445 { 446 xAdp = m_XWeakConnectionPoint; 447 m_XWeakConnectionPoint.clear(); 448 } 449 } 450 451 if( xAdp.is() ) 452 xAdp->removeReference((XReference*)this); 453 } 454 455 //------------------------------------------------------------------------ 456 //-- WeakReferenceHelper ---------------------------------------------------------- 457 //------------------------------------------------------------------------ 458 WeakReferenceHelper::WeakReferenceHelper(const Reference< XInterface >& xInt) SAL_THROW( () ) 459 : m_pImpl( 0 ) 460 { 461 if (xInt.is()) 462 { 463 m_pImpl = new OWeakRefListener(xInt); 464 m_pImpl->acquire(); 465 } 466 } 467 468 WeakReferenceHelper::WeakReferenceHelper(const WeakReferenceHelper& rWeakRef) SAL_THROW( () ) 469 : m_pImpl( 0 ) 470 { 471 Reference< XInterface > xInt( rWeakRef.get() ); 472 if (xInt.is()) 473 { 474 m_pImpl = new OWeakRefListener(xInt); 475 m_pImpl->acquire(); 476 } 477 } 478 479 void WeakReferenceHelper::clear() SAL_THROW( () ) 480 { 481 try 482 { 483 if (m_pImpl) 484 { 485 if (m_pImpl->m_XWeakConnectionPoint.is()) 486 { 487 m_pImpl->m_XWeakConnectionPoint->removeReference( 488 (XReference*)m_pImpl); 489 m_pImpl->m_XWeakConnectionPoint.clear(); 490 } 491 m_pImpl->release(); 492 m_pImpl = 0; 493 } 494 } 495 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected() 496 } 497 498 WeakReferenceHelper& WeakReferenceHelper::operator=(const WeakReferenceHelper& rWeakRef) SAL_THROW( () ) 499 { 500 if (this == &rWeakRef) 501 { 502 return *this; 503 } 504 Reference< XInterface > xInt( rWeakRef.get() ); 505 return operator = ( xInt ); 506 } 507 508 WeakReferenceHelper & SAL_CALL 509 WeakReferenceHelper::operator= (const Reference< XInterface > & xInt) 510 SAL_THROW( () ) 511 { 512 try 513 { 514 clear(); 515 if (xInt.is()) 516 { 517 m_pImpl = new OWeakRefListener(xInt); 518 m_pImpl->acquire(); 519 } 520 } 521 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected() 522 return *this; 523 } 524 525 WeakReferenceHelper::~WeakReferenceHelper() SAL_THROW( () ) 526 { 527 clear(); 528 } 529 530 Reference< XInterface > WeakReferenceHelper::get() const SAL_THROW( () ) 531 { 532 try 533 { 534 Reference< XAdapter > xAdp; 535 { 536 MutexGuard guard(cppu::getWeakMutex()); 537 if( m_pImpl && m_pImpl->m_XWeakConnectionPoint.is() ) 538 xAdp = m_pImpl->m_XWeakConnectionPoint; 539 } 540 541 if (xAdp.is()) 542 return xAdp->queryAdapted(); 543 } 544 catch (RuntimeException &) { OSL_ASSERT( 0 ); } // assert here, but no unexpected() 545 546 return Reference< XInterface >(); 547 } 548 549 } 550 } 551 } 552 } 553 554