1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: interfacecontainer.cxx,v $
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>
43 #if OSL_DEBUG_LEVEL == 0
50 #include <com/sun/star/lang/XEventListener.hpp>
54 using namespace com::sun::star::uno
;
55 using namespace com::sun::star::lang
;
60 //===================================================================
61 //===================================================================
62 //===================================================================
64 * Reallocate the sequence.
66 static void realloc( Sequence
< Reference
< XInterface
> > & rSeq
, sal_Int32 nNewLen
)
69 rSeq
.realloc( nNewLen
);
73 * Remove an element from an interface sequence.
75 static void sequenceRemoveElementAt( Sequence
< Reference
< XInterface
> > & rSeq
, sal_Int32 index
)
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();
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];
93 //-----------------------------------------------------------------------------
94 //-----------------------------------------------------------------------------
97 #pragma warning( disable: 4786 )
100 //===================================================================
101 //===================================================================
102 //===================================================================
103 OInterfaceIteratorHelper::OInterfaceIteratorHelper( OInterfaceContainerHelper
& rCont_
)
107 MutexGuard
aGuard( rCont
.rMutex
);
109 // worst case, two iterators at the same time
110 rCont
.copyAndResetInUse();
111 bIsList
= rCont_
.bIsList
;
112 pData
= rCont_
.pData
;
115 rCont
.bInUse
= sal_True
;
116 nRemain
= ((Sequence
< Reference
< XInterface
> >*)pData
)->getLength();
120 ((XInterface
*)pData
)->acquire();
127 OInterfaceIteratorHelper::~OInterfaceIteratorHelper() SAL_THROW( () )
131 MutexGuard
aGuard( rCont
.rMutex
);
132 // bResetInUse protect the iterator against recursion
133 bShared
= pData
== rCont
.pData
&& rCont
.bIsList
;
136 OSL_ENSURE( rCont
.bInUse
, "OInterfaceContainerHelper must be in use" );
137 rCont
.bInUse
= sal_False
;
144 // Sequence owned by the iterator
145 delete (Sequence
< Reference
< XInterface
> >*)pData
;
147 // Interface is acquired by the iterator
148 ((XInterface
*)pData
)->release();
152 XInterface
* OInterfaceIteratorHelper::next() SAL_THROW( () )
158 // typecase to const,so the getArray method is faster
159 return ((const Sequence
< Reference
< XInterface
> >*)pData
)->getConstArray()[nRemain
].get();
161 return (XInterface
*)pData
;
167 void OInterfaceIteratorHelper::remove() SAL_THROW( () )
171 OSL_ASSERT( nRemain
>= 0 &&
172 nRemain
< ((const Sequence
< Reference
< XInterface
> >*)pData
)->getLength() );
174 ((const Sequence
< Reference
< XInterface
> >*)pData
)->getConstArray()[nRemain
].get();
175 rCont
.removeInterface( * reinterpret_cast< const Reference
< XInterface
> * >( &p
) );
179 OSL_ASSERT( 0 == nRemain
);
180 rCont
.removeInterface( * reinterpret_cast< const Reference
< XInterface
> * >(&pData
));
184 //===================================================================
185 //===================================================================
186 //===================================================================
189 OInterfaceContainerHelper::OInterfaceContainerHelper( Mutex
& rMutex_
) SAL_THROW( () )
192 , bInUse( sal_False
)
193 , bIsList( sal_False
)
197 OInterfaceContainerHelper::~OInterfaceContainerHelper() SAL_THROW( () )
199 OSL_ENSURE( !bInUse
, "~OInterfaceContainerHelper but is in use" );
201 delete (Sequence
< Reference
< XInterface
> >*)pData
;
203 ((XInterface
*)pData
)->release();
206 sal_Int32
OInterfaceContainerHelper::getLength() const SAL_THROW( () )
208 MutexGuard
aGuard( rMutex
);
210 return ((Sequence
< Reference
< XInterface
> >*)pData
)->getLength();
216 Sequence
< Reference
<XInterface
> > OInterfaceContainerHelper::getElements() const SAL_THROW( () )
218 MutexGuard
aGuard( rMutex
);
220 return *(Sequence
< Reference
< XInterface
> >*)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" );
234 // this should be the worst case. If a iterator is active
235 // and a new Listener is added.
237 pData
= new Sequence
< Reference
< XInterface
> >( *(Sequence
< Reference
< XInterface
> >*)pData
);
239 ((XInterface
*)pData
)->acquire();
245 sal_Int32
OInterfaceContainerHelper::addInterface( const Reference
<XInterface
> & rListener
) SAL_THROW( () )
247 OSL_ASSERT( rListener
.is() );
248 MutexGuard
aGuard( rMutex
);
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
;
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();
272 pData
= rListener
.get();
274 rListener
->acquire();
279 sal_Int32
OInterfaceContainerHelper::removeInterface( const Reference
<XInterface
> & rListener
) SAL_THROW( () )
281 OSL_ASSERT( rListener
.is() );
282 MutexGuard
aGuard( rMutex
);
288 const Reference
<XInterface
> * pL
= ((const Sequence
< Reference
< XInterface
> >*)pData
)->getConstArray();
289 sal_Int32 nLen
= ((Sequence
< Reference
< XInterface
> >*)pData
)->getLength();
291 for( i
= 0; i
< nLen
; i
++ )
293 // It is not valid to compare the Pointer direkt, but is is is much
295 if( pL
[i
].get() == rListener
.get() )
297 sequenceRemoveElementAt( *(Sequence
< Reference
< XInterface
> >*)pData
, i
);
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
);
315 if( ((Sequence
< Reference
< XInterface
> >*)pData
)->getLength() == 1 )
317 XInterface
* p
= ((const Sequence
< Reference
< XInterface
> >*)pData
)->getConstArray()[0].get();
319 delete (Sequence
< Reference
< XInterface
> >*)pData
;
325 return ((Sequence
< Reference
< XInterface
> >*)pData
)->getLength();
327 else if( pData
&& Reference
<XInterface
>( (XInterface
*)pData
) == rListener
)
329 ((XInterface
*)pData
)->release();
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
348 while( aIt
.hasMoreElements() )
352 Reference
<XEventListener
> xLst( aIt
.next(), UNO_QUERY
);
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
377 // release mutex before aIt destructor call
381 //##################################################################################################
382 //##################################################################################################
383 //##################################################################################################
385 // specialized class for type
387 typedef ::std::vector
< std::pair
< Type
, void* > > t_type2ptr
;
389 OMultiTypeInterfaceContainerHelper::OMultiTypeInterfaceContainerHelper( Mutex
& rMutex_
)
393 m_pMap
= new t_type2ptr();
395 OMultiTypeInterfaceContainerHelper::~OMultiTypeInterfaceContainerHelper()
398 t_type2ptr
* pMap
= (t_type2ptr
*)m_pMap
;
399 t_type2ptr::iterator iter
= pMap
->begin();
400 t_type2ptr::iterator end
= pMap
->end();
404 delete (OInterfaceContainerHelper
*)(*iter
).second
;
410 Sequence
< Type
> OMultiTypeInterfaceContainerHelper::getContainedTypes() const
413 t_type2ptr
* pMap
= (t_type2ptr
*)m_pMap
;
414 t_type2ptr::size_type nSize
;
416 ::osl::MutexGuard
aGuard( rMutex
);
417 nSize
= pMap
->size();
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();
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
;
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();
451 if (iter
->first
== rKey
)
458 OInterfaceContainerHelper
* OMultiTypeInterfaceContainerHelper::getContainer( const Type
& rKey
) const
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
;
469 sal_Int32
OMultiTypeInterfaceContainerHelper::addInterface(
470 const Type
& rKey
, const Reference
< XInterface
> & rListener
)
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
);
483 return ((OInterfaceContainerHelper
*)(*iter
).second
)->addInterface( rListener
);
485 sal_Int32
OMultiTypeInterfaceContainerHelper::removeInterface(
486 const Type
& rKey
, const Reference
< XInterface
> & rListener
)
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
);
495 if( iter
!= pMap
->end() )
496 return ((OInterfaceContainerHelper
*)(*iter
).second
)->removeInterface( rListener
);
498 // no container with this id. Always return 0
501 void OMultiTypeInterfaceContainerHelper::disposeAndClear( const EventObject
& rEvt
)
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();
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;
522 ppListenerContainers
[i
++] = (OInterfaceContainerHelper
*)(*iter
).second
;
528 // create a copy, because do not fire event in a guarded section
529 for( t_type2ptr::size_type i
= 0;
532 if( ppListenerContainers
[i
] )
533 ppListenerContainers
[i
]->disposeAndClear( rEvt
);
536 delete [] ppListenerContainers
;
538 void OMultiTypeInterfaceContainerHelper::clear()
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();
548 ((OInterfaceContainerHelper
*)(*iter
).second
)->clear();
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();
569 if (iter
->first
== nKey
)
576 OMultiTypeInterfaceContainerHelperInt32::OMultiTypeInterfaceContainerHelperInt32( Mutex
& rMutex_
)
581 // delay pMap allocation until necessary.
583 OMultiTypeInterfaceContainerHelperInt32::~OMultiTypeInterfaceContainerHelperInt32()
589 t_long2ptr
* pMap
= (t_long2ptr
*)m_pMap
;
590 t_long2ptr::iterator iter
= pMap
->begin();
591 t_long2ptr::iterator end
= pMap
->end();
595 delete (OInterfaceContainerHelper
*)(*iter
).second
;
601 Sequence
< sal_Int32
> OMultiTypeInterfaceContainerHelperInt32::getContainedTypes() const
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;
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();
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
;
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
637 ::osl::MutexGuard
aGuard( rMutex
);
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
;
647 sal_Int32
OMultiTypeInterfaceContainerHelperInt32::addInterface(
648 const sal_Int32
& rKey
, const Reference
< XInterface
> & rListener
)
651 ::osl::MutexGuard
aGuard( rMutex
);
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
);
663 return ((OInterfaceContainerHelper
*)(*iter
).second
)->addInterface( rListener
);
665 sal_Int32
OMultiTypeInterfaceContainerHelperInt32::removeInterface(
666 const sal_Int32
& rKey
, const Reference
< XInterface
> & rListener
)
669 ::osl::MutexGuard
aGuard( rMutex
);
673 // search container with id nUik
674 t_long2ptr
* pMap
= (t_long2ptr
*)m_pMap
;
675 t_long2ptr::iterator iter
= findLong( pMap
, rKey
);
677 if( iter
!= pMap
->end() )
678 return ((OInterfaceContainerHelper
*)(*iter
).second
)->removeInterface( rListener
);
680 // no container with this id. Always return 0
683 void OMultiTypeInterfaceContainerHelperInt32::disposeAndClear( const EventObject
& rEvt
)
686 t_long2ptr::size_type nSize
= 0;
687 OInterfaceContainerHelper
** ppListenerContainers
= NULL
;
689 ::osl::MutexGuard
aGuard( rMutex
);
693 t_long2ptr
* pMap
= (t_long2ptr
*)m_pMap
;
694 nSize
= pMap
->size();
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;
707 ppListenerContainers
[i
++] = (OInterfaceContainerHelper
*)(*iter
).second
;
713 // create a copy, because do not fire event in a guarded section
714 for( t_long2ptr::size_type i
= 0;
717 if( ppListenerContainers
[i
] )
718 ppListenerContainers
[i
]->disposeAndClear( rEvt
);
721 delete [] ppListenerContainers
;
723 void OMultiTypeInterfaceContainerHelperInt32::clear()
726 ::osl::MutexGuard
aGuard( rMutex
);
729 t_long2ptr
* pMap
= (t_long2ptr
*)m_pMap
;
730 t_long2ptr::iterator iter
= pMap
->begin();
731 t_long2ptr::iterator end
= pMap
->end();
735 ((OInterfaceContainerHelper
*)(*iter
).second
)->clear();