update dev300-m58
[ooovba.git] / cppuhelper / source / interfacecontainer.cxx
blobbf85843ed7072ffacf27721b17474c72bfd4f5ef
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: interfacecontainer.cxx,v $
10 * $Revision: 1.19 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_cppuhelper.hxx"
34 #include <cppuhelper/interfacecontainer.hxx>
35 #include <cppuhelper/queryinterface.hxx>
36 #include <cppuhelper/propshlp.hxx>
38 #include <osl/diagnose.h>
39 #include <osl/mutex.hxx>
41 #include <hash_map>
43 #if OSL_DEBUG_LEVEL == 0
44 # ifndef NDEBUG
45 # define NDEBUG
46 # endif
47 #endif
48 #include <assert.h>
50 #include <com/sun/star/lang/XEventListener.hpp>
53 using namespace osl;
54 using namespace com::sun::star::uno;
55 using namespace com::sun::star::lang;
57 namespace cppu
60 //===================================================================
61 //===================================================================
62 //===================================================================
63 /**
64 * Reallocate the sequence.
66 static void realloc( Sequence< Reference< XInterface > > & rSeq, sal_Int32 nNewLen )
67 SAL_THROW( () )
69 rSeq.realloc( nNewLen );
72 /**
73 * Remove an element from an interface sequence.
75 static void sequenceRemoveElementAt( Sequence< Reference< XInterface > > & rSeq, sal_Int32 index )
76 SAL_THROW( () )
78 sal_Int32 nNewLen = rSeq.getLength() - 1;
80 Sequence< Reference< XInterface > > aDestSeq( rSeq.getLength() - 1 );
81 // getArray on a const sequence is faster
82 const Reference< XInterface > * pSource = ((const Sequence< Reference< XInterface > > &)rSeq).getConstArray();
83 Reference< XInterface > * pDest = aDestSeq.getArray();
84 sal_Int32 i = 0;
85 for( ; i < index; i++ )
86 pDest[i] = pSource[i];
87 for( sal_Int32 j = i ; j < nNewLen; j++ )
88 pDest[j] = pSource[j+1];
89 rSeq = aDestSeq;
93 //-----------------------------------------------------------------------------
94 //-----------------------------------------------------------------------------
96 #ifdef _MSC_VER
97 #pragma warning( disable: 4786 )
98 #endif
100 //===================================================================
101 //===================================================================
102 //===================================================================
103 OInterfaceIteratorHelper::OInterfaceIteratorHelper( OInterfaceContainerHelper & rCont_ )
104 SAL_THROW( () )
105 : rCont( rCont_ )
107 MutexGuard aGuard( rCont.rMutex );
108 if( rCont.bInUse )
109 // worst case, two iterators at the same time
110 rCont.copyAndResetInUse();
111 bIsList = rCont_.bIsList;
112 pData = rCont_.pData;
113 if( bIsList )
115 rCont.bInUse = sal_True;
116 nRemain = ((Sequence< Reference< XInterface > >*)pData)->getLength();
118 else if( pData )
120 ((XInterface *)pData)->acquire();
121 nRemain = 1;
123 else
124 nRemain = 0;
127 OInterfaceIteratorHelper::~OInterfaceIteratorHelper() SAL_THROW( () )
129 sal_Bool bShared;
131 MutexGuard aGuard( rCont.rMutex );
132 // bResetInUse protect the iterator against recursion
133 bShared = pData == rCont.pData && rCont.bIsList;
134 if( bShared )
136 OSL_ENSURE( rCont.bInUse, "OInterfaceContainerHelper must be in use" );
137 rCont.bInUse = sal_False;
141 if( !bShared )
143 if( bIsList )
144 // Sequence owned by the iterator
145 delete (Sequence< Reference< XInterface > >*)pData;
146 else if( pData )
147 // Interface is acquired by the iterator
148 ((XInterface*)pData)->release();
152 XInterface * OInterfaceIteratorHelper::next() SAL_THROW( () )
154 if( nRemain )
156 nRemain--;
157 if( bIsList )
158 // typecase to const,so the getArray method is faster
159 return ((const Sequence< Reference< XInterface > >*)pData)->getConstArray()[nRemain].get();
160 else if( pData )
161 return (XInterface*)pData;
163 // exception
164 return 0;
167 void OInterfaceIteratorHelper::remove() SAL_THROW( () )
169 if( bIsList )
171 OSL_ASSERT( nRemain >= 0 &&
172 nRemain < ((const Sequence< Reference< XInterface > >*)pData)->getLength() );
173 XInterface * p =
174 ((const Sequence< Reference< XInterface > >*)pData)->getConstArray()[nRemain].get();
175 rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >( &p ) );
177 else
179 OSL_ASSERT( 0 == nRemain );
180 rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >(&pData));
184 //===================================================================
185 //===================================================================
186 //===================================================================
189 OInterfaceContainerHelper::OInterfaceContainerHelper( Mutex & rMutex_ ) SAL_THROW( () )
190 : pData( 0 )
191 , rMutex( rMutex_ )
192 , bInUse( sal_False )
193 , bIsList( sal_False )
197 OInterfaceContainerHelper::~OInterfaceContainerHelper() SAL_THROW( () )
199 OSL_ENSURE( !bInUse, "~OInterfaceContainerHelper but is in use" );
200 if( bIsList )
201 delete (Sequence< Reference< XInterface > >*)pData;
202 else if( pData )
203 ((XInterface*)pData)->release();
206 sal_Int32 OInterfaceContainerHelper::getLength() const SAL_THROW( () )
208 MutexGuard aGuard( rMutex );
209 if( bIsList )
210 return ((Sequence< Reference< XInterface > >*)pData)->getLength();
211 else if( pData )
212 return 1;
213 return 0;
216 Sequence< Reference<XInterface> > OInterfaceContainerHelper::getElements() const SAL_THROW( () )
218 MutexGuard aGuard( rMutex );
219 if( bIsList )
220 return *(Sequence< Reference< XInterface > >*)pData;
221 else if( pData )
223 Reference<XInterface> x( (XInterface *)pData );
224 return Sequence< Reference< XInterface > >( &x, 1 );
226 return Sequence< Reference< XInterface > >();
229 void OInterfaceContainerHelper::copyAndResetInUse() SAL_THROW( () )
231 OSL_ENSURE( bInUse, "OInterfaceContainerHelper not in use" );
232 if( bInUse )
234 // this should be the worst case. If a iterator is active
235 // and a new Listener is added.
236 if( bIsList )
237 pData = new Sequence< Reference< XInterface > >( *(Sequence< Reference< XInterface > >*)pData );
238 else if( pData )
239 ((XInterface*)pData)->acquire();
241 bInUse = sal_False;
245 sal_Int32 OInterfaceContainerHelper::addInterface( const Reference<XInterface> & rListener ) SAL_THROW( () )
247 OSL_ASSERT( rListener.is() );
248 MutexGuard aGuard( rMutex );
249 if( bInUse )
250 copyAndResetInUse();
252 if( bIsList )
254 sal_Int32 nLen = ((Sequence< Reference< XInterface > >*)pData)->getLength();
255 realloc( *(Sequence< Reference< XInterface > >*)pData, nLen +1 );
256 ((Sequence< Reference< XInterface > >*)pData)->getArray()[ nLen ] = rListener;
257 return nLen +1;
259 else if( pData )
261 Sequence< Reference< XInterface > > * pSeq = new Sequence< Reference< XInterface > >( 2 );
262 Reference<XInterface> * pArray = pSeq->getArray();
263 pArray[0] = (XInterface *)pData;
264 pArray[1] = rListener;
265 ((XInterface *)pData)->release();
266 pData = pSeq;
267 bIsList = sal_True;
268 return 2;
270 else
272 pData = rListener.get();
273 if( rListener.is() )
274 rListener->acquire();
275 return 1;
279 sal_Int32 OInterfaceContainerHelper::removeInterface( const Reference<XInterface> & rListener ) SAL_THROW( () )
281 OSL_ASSERT( rListener.is() );
282 MutexGuard aGuard( rMutex );
283 if( bInUse )
284 copyAndResetInUse();
286 if( bIsList )
288 const Reference<XInterface> * pL = ((const Sequence< Reference< XInterface > >*)pData)->getConstArray();
289 sal_Int32 nLen = ((Sequence< Reference< XInterface > >*)pData)->getLength();
290 sal_Int32 i;
291 for( i = 0; i < nLen; i++ )
293 // It is not valid to compare the Pointer direkt, but is is is much
294 // more faster.
295 if( pL[i].get() == rListener.get() )
297 sequenceRemoveElementAt( *(Sequence< Reference< XInterface > >*)pData, i );
298 break;
302 if( i == nLen )
304 // interface not found, use the correct compare method
305 for( i = 0; i < nLen; i++ )
307 if( pL[i] == rListener )
309 sequenceRemoveElementAt(*(Sequence< Reference< XInterface > >*)pData, i );
310 break;
315 if( ((Sequence< Reference< XInterface > >*)pData)->getLength() == 1 )
317 XInterface * p = ((const Sequence< Reference< XInterface > >*)pData)->getConstArray()[0].get();
318 p->acquire();
319 delete (Sequence< Reference< XInterface > >*)pData;
320 pData = p;
321 bIsList = sal_False;
322 return 1;
324 else
325 return ((Sequence< Reference< XInterface > >*)pData)->getLength();
327 else if( pData && Reference<XInterface>( (XInterface*)pData ) == rListener )
329 ((XInterface *)pData)->release();
330 pData = 0;
332 return pData ? 1 : 0;
335 void OInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt ) SAL_THROW( () )
337 ClearableMutexGuard aGuard( rMutex );
338 OInterfaceIteratorHelper aIt( *this );
339 // Container freigeben, falls im disposing neue Einträge kommen
340 OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" );
341 if( !bIsList && pData )
342 ((XInterface *)pData)->release();
343 // set the member to null, the iterator delete the values
344 pData = NULL;
345 bIsList = sal_False;
346 bInUse = sal_False;
347 aGuard.clear();
348 while( aIt.hasMoreElements() )
352 Reference<XEventListener > xLst( aIt.next(), UNO_QUERY );
353 if( xLst.is() )
354 xLst->disposing( rEvt );
356 catch ( RuntimeException & )
358 // be robust, if e.g. a remote bridge has disposed already.
359 // there is no way, to delegate the error to the caller :o(.
365 void OInterfaceContainerHelper::clear() SAL_THROW( () )
367 ClearableMutexGuard aGuard( rMutex );
368 OInterfaceIteratorHelper aIt( *this );
369 // Container freigeben, falls im disposing neue Einträge kommen
370 OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper not in use" );
371 if( !bIsList && pData )
372 ((XInterface *)pData)->release();
373 // set the member to null, the iterator delete the values
374 pData = 0;
375 bIsList = sal_False;
376 bInUse = sal_False;
377 // release mutex before aIt destructor call
378 aGuard.clear();
381 //##################################################################################################
382 //##################################################################################################
383 //##################################################################################################
385 // specialized class for type
387 typedef ::std::vector< std::pair < Type , void* > > t_type2ptr;
389 OMultiTypeInterfaceContainerHelper::OMultiTypeInterfaceContainerHelper( Mutex & rMutex_ )
390 SAL_THROW( () )
391 : rMutex( rMutex_ )
393 m_pMap = new t_type2ptr();
395 OMultiTypeInterfaceContainerHelper::~OMultiTypeInterfaceContainerHelper()
396 SAL_THROW( () )
398 t_type2ptr * pMap = (t_type2ptr *)m_pMap;
399 t_type2ptr::iterator iter = pMap->begin();
400 t_type2ptr::iterator end = pMap->end();
402 while( iter != end )
404 delete (OInterfaceContainerHelper*)(*iter).second;
405 (*iter).second = 0;
406 ++iter;
408 delete pMap;
410 Sequence< Type > OMultiTypeInterfaceContainerHelper::getContainedTypes() const
411 SAL_THROW( () )
413 t_type2ptr * pMap = (t_type2ptr *)m_pMap;
414 t_type2ptr::size_type nSize;
416 ::osl::MutexGuard aGuard( rMutex );
417 nSize = pMap->size();
418 if( nSize )
420 ::com::sun::star::uno::Sequence< Type > aInterfaceTypes( nSize );
421 Type * pArray = aInterfaceTypes.getArray();
423 t_type2ptr::iterator iter = pMap->begin();
424 t_type2ptr::iterator end = pMap->end();
426 sal_Int32 i = 0;
427 while( iter != end )
429 // are interfaces added to this container?
430 if( ((OInterfaceContainerHelper*)(*iter).second)->getLength() )
431 // yes, put the type in the array
432 pArray[i++] = (*iter).first;
433 ++iter;
435 if( (t_type2ptr::size_type)i != nSize ) {
436 // may be empty container, reduce the sequence to the right size
437 aInterfaceTypes = ::com::sun::star::uno::Sequence< Type >( pArray, i );
439 return aInterfaceTypes;
441 return ::com::sun::star::uno::Sequence< Type >();
444 static t_type2ptr::iterator findType(t_type2ptr *pMap, const Type & rKey )
446 t_type2ptr::iterator iter = pMap->begin();
447 t_type2ptr::iterator end = pMap->end();
449 while( iter != end )
451 if (iter->first == rKey)
452 break;
453 iter++;
455 return iter;
458 OInterfaceContainerHelper * OMultiTypeInterfaceContainerHelper::getContainer( const Type & rKey ) const
459 SAL_THROW( () )
461 ::osl::MutexGuard aGuard( rMutex );
463 t_type2ptr * pMap = (t_type2ptr *)m_pMap;
464 t_type2ptr::iterator iter = findType( pMap, rKey );
465 if( iter != pMap->end() )
466 return (OInterfaceContainerHelper*) (*iter).second;
467 return 0;
469 sal_Int32 OMultiTypeInterfaceContainerHelper::addInterface(
470 const Type & rKey, const Reference< XInterface > & rListener )
471 SAL_THROW( () )
473 ::osl::MutexGuard aGuard( rMutex );
474 t_type2ptr * pMap = (t_type2ptr *)m_pMap;
475 t_type2ptr::iterator iter = findType( pMap, rKey );
476 if( iter == pMap->end() )
478 OInterfaceContainerHelper * pLC = new OInterfaceContainerHelper( rMutex );
479 pMap->push_back(std::pair<Type, void*>(rKey, pLC));
480 return pLC->addInterface( rListener );
482 else
483 return ((OInterfaceContainerHelper*)(*iter).second)->addInterface( rListener );
485 sal_Int32 OMultiTypeInterfaceContainerHelper::removeInterface(
486 const Type & rKey, const Reference< XInterface > & rListener )
487 SAL_THROW( () )
489 ::osl::MutexGuard aGuard( rMutex );
491 // search container with id nUik
492 t_type2ptr * pMap = (t_type2ptr *)m_pMap;
493 t_type2ptr::iterator iter = findType( pMap, rKey );
494 // container found?
495 if( iter != pMap->end() )
496 return ((OInterfaceContainerHelper*)(*iter).second)->removeInterface( rListener );
498 // no container with this id. Always return 0
499 return 0;
501 void OMultiTypeInterfaceContainerHelper::disposeAndClear( const EventObject & rEvt )
502 SAL_THROW( () )
504 t_type2ptr::size_type nSize = 0;
505 OInterfaceContainerHelper ** ppListenerContainers = NULL;
507 ::osl::MutexGuard aGuard( rMutex );
508 t_type2ptr * pMap = (t_type2ptr *)m_pMap;
509 nSize = pMap->size();
510 if( nSize )
512 typedef OInterfaceContainerHelper* ppp;
513 ppListenerContainers = new ppp[nSize];
514 //ppListenerContainers = new (ListenerContainer*)[nSize];
516 t_type2ptr::iterator iter = pMap->begin();
517 t_type2ptr::iterator end = pMap->end();
519 t_type2ptr::size_type i = 0;
520 while( iter != end )
522 ppListenerContainers[i++] = (OInterfaceContainerHelper*)(*iter).second;
523 ++iter;
528 // create a copy, because do not fire event in a guarded section
529 for( t_type2ptr::size_type i = 0;
530 i < nSize; i++ )
532 if( ppListenerContainers[i] )
533 ppListenerContainers[i]->disposeAndClear( rEvt );
536 delete [] ppListenerContainers;
538 void OMultiTypeInterfaceContainerHelper::clear()
539 SAL_THROW( () )
541 ::osl::MutexGuard aGuard( rMutex );
542 t_type2ptr * pMap = (t_type2ptr *)m_pMap;
543 t_type2ptr::iterator iter = pMap->begin();
544 t_type2ptr::iterator end = pMap->end();
546 while( iter != end )
548 ((OInterfaceContainerHelper*)(*iter).second)->clear();
549 ++iter;
554 //##################################################################################################
555 //##################################################################################################
556 //##################################################################################################
558 // specialized class for long
560 typedef ::std::vector< std::pair < sal_Int32 , void* > > t_long2ptr;
562 static t_long2ptr::iterator findLong(t_long2ptr *pMap, sal_Int32 nKey )
564 t_long2ptr::iterator iter = pMap->begin();
565 t_long2ptr::iterator end = pMap->end();
567 while( iter != end )
569 if (iter->first == nKey)
570 break;
571 iter++;
573 return iter;
576 OMultiTypeInterfaceContainerHelperInt32::OMultiTypeInterfaceContainerHelperInt32( Mutex & rMutex_ )
577 SAL_THROW( () )
578 : m_pMap( NULL )
579 , rMutex( rMutex_ )
581 // delay pMap allocation until necessary.
583 OMultiTypeInterfaceContainerHelperInt32::~OMultiTypeInterfaceContainerHelperInt32()
584 SAL_THROW( () )
586 if (!m_pMap)
587 return;
589 t_long2ptr * pMap = (t_long2ptr *)m_pMap;
590 t_long2ptr::iterator iter = pMap->begin();
591 t_long2ptr::iterator end = pMap->end();
593 while( iter != end )
595 delete (OInterfaceContainerHelper*)(*iter).second;
596 (*iter).second = 0;
597 ++iter;
599 delete pMap;
601 Sequence< sal_Int32 > OMultiTypeInterfaceContainerHelperInt32::getContainedTypes() const
602 SAL_THROW( () )
604 t_long2ptr * pMap = (t_long2ptr *)m_pMap;
605 t_long2ptr::size_type nSize;
607 ::osl::MutexGuard aGuard( rMutex );
608 nSize = pMap ? pMap->size() : 0;
609 if( nSize )
611 ::com::sun::star::uno::Sequence< sal_Int32 > aInterfaceTypes( nSize );
612 sal_Int32 * pArray = aInterfaceTypes.getArray();
614 t_long2ptr::iterator iter = pMap->begin();
615 t_long2ptr::iterator end = pMap->end();
617 sal_Int32 i = 0;
618 while( iter != end )
620 // are interfaces added to this container?
621 if( ((OInterfaceContainerHelper*)(*iter).second)->getLength() )
622 // yes, put the type in the array
623 pArray[i++] = (*iter).first;
624 ++iter;
626 if( (t_long2ptr::size_type)i != nSize ) {
627 // may be empty container, reduce the sequence to the right size
628 aInterfaceTypes = ::com::sun::star::uno::Sequence< sal_Int32 >( pArray, i );
630 return aInterfaceTypes;
632 return ::com::sun::star::uno::Sequence< sal_Int32 >();
634 OInterfaceContainerHelper * OMultiTypeInterfaceContainerHelperInt32::getContainer( const sal_Int32 & rKey ) const
635 SAL_THROW( () )
637 ::osl::MutexGuard aGuard( rMutex );
639 if (!m_pMap)
640 return 0;
641 t_long2ptr * pMap = (t_long2ptr *)m_pMap;
642 t_long2ptr::iterator iter = findLong( pMap, rKey );
643 if( iter != pMap->end() )
644 return (OInterfaceContainerHelper*) (*iter).second;
645 return 0;
647 sal_Int32 OMultiTypeInterfaceContainerHelperInt32::addInterface(
648 const sal_Int32 & rKey, const Reference< XInterface > & rListener )
649 SAL_THROW( () )
651 ::osl::MutexGuard aGuard( rMutex );
652 if (!m_pMap)
653 m_pMap = new t_long2ptr();
654 t_long2ptr * pMap = (t_long2ptr *)m_pMap;
655 t_long2ptr::iterator iter = findLong( pMap, rKey );
656 if( iter == pMap->end() )
658 OInterfaceContainerHelper * pLC = new OInterfaceContainerHelper( rMutex );
659 pMap->push_back(std::pair< sal_Int32, void* >(rKey, pLC));
660 return pLC->addInterface( rListener );
662 else
663 return ((OInterfaceContainerHelper*)(*iter).second)->addInterface( rListener );
665 sal_Int32 OMultiTypeInterfaceContainerHelperInt32::removeInterface(
666 const sal_Int32 & rKey, const Reference< XInterface > & rListener )
667 SAL_THROW( () )
669 ::osl::MutexGuard aGuard( rMutex );
671 if (!m_pMap)
672 return 0;
673 // search container with id nUik
674 t_long2ptr * pMap = (t_long2ptr *)m_pMap;
675 t_long2ptr::iterator iter = findLong( pMap, rKey );
676 // container found?
677 if( iter != pMap->end() )
678 return ((OInterfaceContainerHelper*)(*iter).second)->removeInterface( rListener );
680 // no container with this id. Always return 0
681 return 0;
683 void OMultiTypeInterfaceContainerHelperInt32::disposeAndClear( const EventObject & rEvt )
684 SAL_THROW( () )
686 t_long2ptr::size_type nSize = 0;
687 OInterfaceContainerHelper ** ppListenerContainers = NULL;
689 ::osl::MutexGuard aGuard( rMutex );
690 if (!m_pMap)
691 return;
693 t_long2ptr * pMap = (t_long2ptr *)m_pMap;
694 nSize = pMap->size();
695 if( nSize )
697 typedef OInterfaceContainerHelper* ppp;
698 ppListenerContainers = new ppp[nSize];
699 //ppListenerContainers = new (ListenerContainer*)[nSize];
701 t_long2ptr::iterator iter = pMap->begin();
702 t_long2ptr::iterator end = pMap->end();
704 t_long2ptr::size_type i = 0;
705 while( iter != end )
707 ppListenerContainers[i++] = (OInterfaceContainerHelper*)(*iter).second;
708 ++iter;
713 // create a copy, because do not fire event in a guarded section
714 for( t_long2ptr::size_type i = 0;
715 i < nSize; i++ )
717 if( ppListenerContainers[i] )
718 ppListenerContainers[i]->disposeAndClear( rEvt );
721 delete [] ppListenerContainers;
723 void OMultiTypeInterfaceContainerHelperInt32::clear()
724 SAL_THROW( () )
726 ::osl::MutexGuard aGuard( rMutex );
727 if (!m_pMap)
728 return;
729 t_long2ptr * pMap = (t_long2ptr *)m_pMap;
730 t_long2ptr::iterator iter = pMap->begin();
731 t_long2ptr::iterator end = pMap->end();
733 while( iter != end )
735 ((OInterfaceContainerHelper*)(*iter).second)->clear();
736 ++iter;