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