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