#i111793# make cppuhelper/interfacecontainer strict aliasing safe

This commit is contained in:
Caolán McNamara
2010-10-18 16:15:57 +01:00
parent 522faf9ccb
commit 2048cbbfad
2 changed files with 71 additions and 60 deletions

View File

@@ -44,6 +44,17 @@
namespace cppu namespace cppu
{ {
namespace detail {
union element_alias
{
::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > > *pAsSequence;
::com::sun::star::uno::XInterface * pAsInterface;
element_alias() : pAsInterface(0) {}
};
}
//=================================================================== //===================================================================
class OInterfaceContainerHelper; class OInterfaceContainerHelper;
/** /**
@@ -95,7 +106,9 @@ public:
private: private:
OInterfaceContainerHelper & rCont; OInterfaceContainerHelper & rCont;
sal_Bool bIsList; sal_Bool bIsList;
void * pData;
detail::element_alias aData;
sal_Int32 nRemain; sal_Int32 nRemain;
OInterfaceIteratorHelper( const OInterfaceIteratorHelper & ) SAL_THROW( () ); OInterfaceIteratorHelper( const OInterfaceIteratorHelper & ) SAL_THROW( () );
@@ -222,14 +235,14 @@ public:
private: private:
friend class OInterfaceIteratorHelper; friend class OInterfaceIteratorHelper;
/** /**
bIsList == TRUE -> pData of type Sequence< XInterfaceSequence >, bIsList == TRUE -> aData.pAsSequence of type Sequence< XInterfaceSequence >,
otherwise pData == of type (XEventListener *) otherwise aData.pAsInterface == of type (XEventListener *)
*/ */
void * pData; detail::element_alias aData;
::osl::Mutex & rMutex; ::osl::Mutex & rMutex;
/** TRUE -> used by an iterator. */ /** TRUE -> used by an iterator. */
sal_Bool bInUse; sal_Bool bInUse;
/** TRUE -> pData is of type Sequence< XInterfaceSequence >. */ /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
sal_Bool bIsList; sal_Bool bIsList;
OInterfaceContainerHelper( const OInterfaceContainerHelper & ) SAL_THROW( () ); OInterfaceContainerHelper( const OInterfaceContainerHelper & ) SAL_THROW( () );

View File

@@ -100,15 +100,15 @@ OInterfaceIteratorHelper::OInterfaceIteratorHelper( OInterfaceContainerHelper &
// worst case, two iterators at the same time // worst case, two iterators at the same time
rCont.copyAndResetInUse(); rCont.copyAndResetInUse();
bIsList = rCont_.bIsList; bIsList = rCont_.bIsList;
pData = rCont_.pData; aData = rCont_.aData;
if( bIsList ) if( bIsList )
{ {
rCont.bInUse = sal_True; rCont.bInUse = sal_True;
nRemain = ((Sequence< Reference< XInterface > >*)pData)->getLength(); nRemain = aData.pAsSequence->getLength();
} }
else if( pData ) else if( aData.pAsInterface )
{ {
((XInterface *)pData)->acquire(); aData.pAsInterface->acquire();
nRemain = 1; nRemain = 1;
} }
else else
@@ -121,7 +121,7 @@ OInterfaceIteratorHelper::~OInterfaceIteratorHelper() SAL_THROW( () )
{ {
MutexGuard aGuard( rCont.rMutex ); MutexGuard aGuard( rCont.rMutex );
// bResetInUse protect the iterator against recursion // bResetInUse protect the iterator against recursion
bShared = pData == rCont.pData && rCont.bIsList; bShared = aData.pAsSequence == rCont.aData.pAsSequence && rCont.bIsList;
if( bShared ) if( bShared )
{ {
OSL_ENSURE( rCont.bInUse, "OInterfaceContainerHelper must be in use" ); OSL_ENSURE( rCont.bInUse, "OInterfaceContainerHelper must be in use" );
@@ -133,10 +133,10 @@ OInterfaceIteratorHelper::~OInterfaceIteratorHelper() SAL_THROW( () )
{ {
if( bIsList ) if( bIsList )
// Sequence owned by the iterator // Sequence owned by the iterator
delete (Sequence< Reference< XInterface > >*)pData; delete aData.pAsSequence;
else if( pData ) else if( aData.pAsInterface )
// Interface is acquired by the iterator // Interface is acquired by the iterator
((XInterface*)pData)->release(); aData.pAsInterface->release();
} }
} }
@@ -147,9 +147,9 @@ XInterface * OInterfaceIteratorHelper::next() SAL_THROW( () )
nRemain--; nRemain--;
if( bIsList ) if( bIsList )
// typecase to const,so the getArray method is faster // typecase to const,so the getArray method is faster
return ((const Sequence< Reference< XInterface > >*)pData)->getConstArray()[nRemain].get(); return aData.pAsSequence->getConstArray()[nRemain].get();
else if( pData ) else if( aData.pAsInterface )
return (XInterface*)pData; return aData.pAsInterface;
} }
// exception // exception
return 0; return 0;
@@ -160,15 +160,14 @@ void OInterfaceIteratorHelper::remove() SAL_THROW( () )
if( bIsList ) if( bIsList )
{ {
OSL_ASSERT( nRemain >= 0 && OSL_ASSERT( nRemain >= 0 &&
nRemain < ((const Sequence< Reference< XInterface > >*)pData)->getLength() ); nRemain < aData.pAsSequence->getLength() );
XInterface * p = XInterface * p = aData.pAsSequence->getConstArray()[nRemain].get();
((const Sequence< Reference< XInterface > >*)pData)->getConstArray()[nRemain].get();
rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >( &p ) ); rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >( &p ) );
} }
else else
{ {
OSL_ASSERT( 0 == nRemain ); OSL_ASSERT( 0 == nRemain );
rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >(&pData)); rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >(&aData.pAsInterface));
} }
} }
@@ -178,8 +177,7 @@ void OInterfaceIteratorHelper::remove() SAL_THROW( () )
OInterfaceContainerHelper::OInterfaceContainerHelper( Mutex & rMutex_ ) SAL_THROW( () ) OInterfaceContainerHelper::OInterfaceContainerHelper( Mutex & rMutex_ ) SAL_THROW( () )
: pData( 0 ) : rMutex( rMutex_ )
, rMutex( rMutex_ )
, bInUse( sal_False ) , bInUse( sal_False )
, bIsList( sal_False ) , bIsList( sal_False )
{ {
@@ -189,17 +187,17 @@ OInterfaceContainerHelper::~OInterfaceContainerHelper() SAL_THROW( () )
{ {
OSL_ENSURE( !bInUse, "~OInterfaceContainerHelper but is in use" ); OSL_ENSURE( !bInUse, "~OInterfaceContainerHelper but is in use" );
if( bIsList ) if( bIsList )
delete (Sequence< Reference< XInterface > >*)pData; delete aData.pAsSequence;
else if( pData ) else if( aData.pAsInterface )
((XInterface*)pData)->release(); aData.pAsInterface->release();
} }
sal_Int32 OInterfaceContainerHelper::getLength() const SAL_THROW( () ) sal_Int32 OInterfaceContainerHelper::getLength() const SAL_THROW( () )
{ {
MutexGuard aGuard( rMutex ); MutexGuard aGuard( rMutex );
if( bIsList ) if( bIsList )
return ((Sequence< Reference< XInterface > >*)pData)->getLength(); return aData.pAsSequence->getLength();
else if( pData ) else if( aData.pAsInterface )
return 1; return 1;
return 0; return 0;
} }
@@ -208,10 +206,10 @@ Sequence< Reference<XInterface> > OInterfaceContainerHelper::getElements() const
{ {
MutexGuard aGuard( rMutex ); MutexGuard aGuard( rMutex );
if( bIsList ) if( bIsList )
return *(Sequence< Reference< XInterface > >*)pData; return *aData.pAsSequence;
else if( pData ) else if( aData.pAsInterface )
{ {
Reference<XInterface> x( (XInterface *)pData ); Reference<XInterface> x( aData.pAsInterface );
return Sequence< Reference< XInterface > >( &x, 1 ); return Sequence< Reference< XInterface > >( &x, 1 );
} }
return Sequence< Reference< XInterface > >(); return Sequence< Reference< XInterface > >();
@@ -225,9 +223,9 @@ void OInterfaceContainerHelper::copyAndResetInUse() SAL_THROW( () )
// this should be the worst case. If a iterator is active // this should be the worst case. If a iterator is active
// and a new Listener is added. // and a new Listener is added.
if( bIsList ) if( bIsList )
pData = new Sequence< Reference< XInterface > >( *(Sequence< Reference< XInterface > >*)pData ); aData.pAsSequence = new Sequence< Reference< XInterface > >( *aData.pAsSequence );
else if( pData ) else if( aData.pAsInterface )
((XInterface*)pData)->acquire(); aData.pAsInterface->acquire();
bInUse = sal_False; bInUse = sal_False;
} }
@@ -242,25 +240,25 @@ sal_Int32 OInterfaceContainerHelper::addInterface( const Reference<XInterface> &
if( bIsList ) if( bIsList )
{ {
sal_Int32 nLen = ((Sequence< Reference< XInterface > >*)pData)->getLength(); sal_Int32 nLen = aData.pAsSequence->getLength();
realloc( *(Sequence< Reference< XInterface > >*)pData, nLen +1 ); realloc( *aData.pAsSequence, nLen +1 );
((Sequence< Reference< XInterface > >*)pData)->getArray()[ nLen ] = rListener; aData.pAsSequence->getArray()[ nLen ] = rListener;
return nLen +1; return nLen +1;
} }
else if( pData ) else if( aData.pAsInterface )
{ {
Sequence< Reference< XInterface > > * pSeq = new Sequence< Reference< XInterface > >( 2 ); Sequence< Reference< XInterface > > * pSeq = new Sequence< Reference< XInterface > >( 2 );
Reference<XInterface> * pArray = pSeq->getArray(); Reference<XInterface> * pArray = pSeq->getArray();
pArray[0] = (XInterface *)pData; pArray[0] = aData.pAsInterface;
pArray[1] = rListener; pArray[1] = rListener;
((XInterface *)pData)->release(); aData.pAsInterface->release();
pData = pSeq; aData.pAsSequence = pSeq;
bIsList = sal_True; bIsList = sal_True;
return 2; return 2;
} }
else else
{ {
pData = rListener.get(); aData.pAsInterface = rListener.get();
if( rListener.is() ) if( rListener.is() )
rListener->acquire(); rListener->acquire();
return 1; return 1;
@@ -276,8 +274,8 @@ sal_Int32 OInterfaceContainerHelper::removeInterface( const Reference<XInterface
if( bIsList ) if( bIsList )
{ {
const Reference<XInterface> * pL = ((const Sequence< Reference< XInterface > >*)pData)->getConstArray(); const Reference<XInterface> * pL = aData.pAsSequence->getConstArray();
sal_Int32 nLen = ((Sequence< Reference< XInterface > >*)pData)->getLength(); sal_Int32 nLen = aData.pAsSequence->getLength();
sal_Int32 i; sal_Int32 i;
for( i = 0; i < nLen; i++ ) for( i = 0; i < nLen; i++ )
{ {
@@ -285,7 +283,7 @@ sal_Int32 OInterfaceContainerHelper::removeInterface( const Reference<XInterface
// more faster. // more faster.
if( pL[i].get() == rListener.get() ) if( pL[i].get() == rListener.get() )
{ {
sequenceRemoveElementAt( *(Sequence< Reference< XInterface > >*)pData, i ); sequenceRemoveElementAt( *aData.pAsSequence, i );
break; break;
} }
} }
@@ -297,30 +295,30 @@ sal_Int32 OInterfaceContainerHelper::removeInterface( const Reference<XInterface
{ {
if( pL[i] == rListener ) if( pL[i] == rListener )
{ {
sequenceRemoveElementAt(*(Sequence< Reference< XInterface > >*)pData, i ); sequenceRemoveElementAt(*aData.pAsSequence, i );
break; break;
} }
} }
} }
if( ((Sequence< Reference< XInterface > >*)pData)->getLength() == 1 ) if( aData.pAsSequence->getLength() == 1 )
{ {
XInterface * p = ((const Sequence< Reference< XInterface > >*)pData)->getConstArray()[0].get(); XInterface * p = aData.pAsSequence->getConstArray()[0].get();
p->acquire(); p->acquire();
delete (Sequence< Reference< XInterface > >*)pData; delete aData.pAsSequence;
pData = p; aData.pAsInterface = p;
bIsList = sal_False; bIsList = sal_False;
return 1; return 1;
} }
else else
return ((Sequence< Reference< XInterface > >*)pData)->getLength(); return aData.pAsSequence->getLength();
} }
else if( pData && Reference<XInterface>( (XInterface*)pData ) == rListener ) else if( aData.pAsInterface && Reference<XInterface>( aData.pAsInterface ) == rListener )
{ {
((XInterface *)pData)->release(); aData.pAsInterface->release();
pData = 0; aData.pAsInterface = 0;
} }
return pData ? 1 : 0; return aData.pAsInterface ? 1 : 0;
} }
void OInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt ) SAL_THROW( () ) void OInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt ) SAL_THROW( () )
@@ -329,10 +327,10 @@ void OInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt ) SAL_
OInterfaceIteratorHelper aIt( *this ); OInterfaceIteratorHelper aIt( *this );
// Release container, in case new entries come while disposing // Release container, in case new entries come while disposing
OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" ); OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" );
if( !bIsList && pData ) if( !bIsList && aData.pAsInterface )
((XInterface *)pData)->release(); aData.pAsInterface->release();
// set the member to null, use the iterator to delete the values // set the member to null, use the iterator to delete the values
pData = NULL; aData.pAsInterface = NULL;
bIsList = sal_False; bIsList = sal_False;
bInUse = sal_False; bInUse = sal_False;
aGuard.clear(); aGuard.clear();
@@ -359,10 +357,10 @@ void OInterfaceContainerHelper::clear() SAL_THROW( () )
OInterfaceIteratorHelper aIt( *this ); OInterfaceIteratorHelper aIt( *this );
// Release container, in case new entries come while disposing // Release container, in case new entries come while disposing
OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" ); OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" );
if( !bIsList && pData ) if( !bIsList && aData.pAsInterface )
((XInterface *)pData)->release(); aData.pAsInterface->release();
// set the member to null, use the iterator to delete the values // set the member to null, use the iterator to delete the values
pData = 0; aData.pAsInterface = 0;
bIsList = sal_False; bIsList = sal_False;
bInUse = sal_False; bInUse = sal_False;
// release mutex before aIt destructor call // release mutex before aIt destructor call