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