1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #ifndef _CPPUHELPER_INTERFACECONTAINER_H_
20 #define _CPPUHELPER_INTERFACECONTAINER_H_
23 #include <osl/mutex.hxx>
24 #include <rtl/alloc.h>
25 #include <com/sun/star/uno/Sequence.hxx>
26 #include <com/sun/star/uno/XInterface.hpp>
27 #include <com/sun/star/lang/EventObject.hpp>
29 #include "com/sun/star/lang/DisposedException.hpp"
30 #include "cppuhelperdllapi.h"
40 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> > *pAsSequence
;
41 ::com::sun::star::uno::XInterface
* pAsInterface
;
42 element_alias() : pAsInterface(0) {}
47 //===================================================================
48 class OInterfaceContainerHelper
;
50 This is the iterator of a InterfaceContainerHelper. Typically
51 one constructs an instance on the stack for one firing session.
52 It is not allowed to assign or copy an instance of this class.
54 @see OInterfaceContainerHelper
56 class CPPUHELPER_DLLPUBLIC OInterfaceIteratorHelper
60 Create an iterator over the elements of the container. The iterator
61 copies the elements of the conatainer. A change to the container
62 during the lifetime of an iterator is allowed and does not
63 affect the iterator-instance. The iterator and the container take cares
64 themself for concurrent access, no additional guarding is necessary.
66 Remark: The copy is on demand. The iterator copy the elements only if the container
67 change the contents. It is not allowed to destroy the container as long
70 @param rCont the container of the elements.
72 OInterfaceIteratorHelper( OInterfaceContainerHelper
& rCont
) SAL_THROW(());
75 Releases the connection to the container.
77 ~OInterfaceIteratorHelper() SAL_THROW(());
79 /** Return sal_True, if there are more elements in the iterator. */
80 sal_Bool SAL_CALL
hasMoreElements() const SAL_THROW(())
81 { return nRemain
!= 0; }
82 /** Return the next element of the iterator. Calling this method if
83 hasMoreElements() has returned sal_False, is an error. Cast the
84 returned pointer to the
86 ::com::sun::star::uno::XInterface
* SAL_CALL
next() SAL_THROW(());
88 /** Removes the current element (the last one returned by next())
89 from the underlying container. Calling this method before
90 next() has been called or calling it twice with no next()
91 inbetween is an error.
93 void SAL_CALL
remove() SAL_THROW(());
96 OInterfaceContainerHelper
& rCont
;
99 detail::element_alias aData
;
103 OInterfaceIteratorHelper( const OInterfaceIteratorHelper
& ) SAL_THROW(());
104 OInterfaceIteratorHelper
& operator = ( const OInterfaceIteratorHelper
& ) SAL_THROW(());
107 //===================================================================
109 A container of interfaces. To access the elements use an iterator.
110 This implementation is thread save.
112 @see OInterfaceIteratorHelper
114 class CPPUHELPER_DLLPUBLIC OInterfaceContainerHelper
117 // these are here to force memory de/allocation to sal lib.
118 inline static void * SAL_CALL
operator new( size_t nSize
) SAL_THROW(())
119 { return ::rtl_allocateMemory( nSize
); }
120 inline static void SAL_CALL
operator delete( void * pMem
) SAL_THROW(())
121 { ::rtl_freeMemory( pMem
); }
122 inline static void * SAL_CALL
operator new( size_t, void * pMem
) SAL_THROW(())
124 inline static void SAL_CALL
operator delete( void *, void * ) SAL_THROW(())
128 Create an interface container.
130 @param rMutex the mutex to protect multi thread access.
131 The lifetime must be longer than the lifetime
134 OInterfaceContainerHelper( ::osl::Mutex
& rMutex
) SAL_THROW(());
136 Release all interfaces. All iterators must be destroyed before
137 the container is destructed.
139 ~OInterfaceContainerHelper() SAL_THROW(());
141 Return the number of Elements in the container. Only useful if you have acquired
144 sal_Int32 SAL_CALL
getLength() const SAL_THROW(());
147 Return all interfaces added to this container.
149 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> > SAL_CALL
getElements() const SAL_THROW(());
151 /** Inserts an element into the container. The position is not specified, thus it is not
152 specified in which order events are fired.
155 If you add the same interface more than once, then it will be added to the elements list
156 more than once and thus if you want to remove that interface from the list, you have to call
157 removeInterface() the same number of times.
158 In the latter case, you will also get events fired more than once (if the interface is a
162 interface to be added; it is allowed to insert null or
163 the same interface more than once
165 the new count of elements in the container
167 sal_Int32 SAL_CALL
addInterface( const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & rxIFace
) SAL_THROW(());
168 /** Removes an element from the container. It uses interface equality to remove the interface.
171 interface to be removed
173 the new count of elements in the container
175 sal_Int32 SAL_CALL
removeInterface( const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & rxIFace
) SAL_THROW(());
177 Call disposing on all object in the container that
178 support XEventListener. Than clear the container.
180 void SAL_CALL
disposeAndClear( const ::com::sun::star::lang::EventObject
& rEvt
) SAL_THROW(());
182 Clears the container without calling disposing().
184 void SAL_CALL
clear() SAL_THROW(());
186 /** Executes a functor for each contained listener of specified type, e.g.
187 <code>forEach<awt::XPaintListener>(...</code>.
189 If a com::sun::star::lang::DisposedException occurs which relates to
190 the called listener, then that listener is removed from the container.
192 @tparam ListenerT listener type
193 @tparam FuncT unary functor type, let your compiler deduce this for you
194 @param func unary functor object expecting an argument of type
195 com::sun::star::uno::Reference<ListenerT>
197 template <typename ListenerT
, typename FuncT
>
198 inline void forEach( FuncT
const& func
);
200 /** Calls a UNO listener method for each contained listener.
202 The listener method must take a single argument of type EventT,
203 and return <code>void</code>.
205 If a com::sun::star::lang::DisposedException occurs which relates to
206 the called listener, then that listener is removed from the container.
208 @tparam ListenerT UNO event listener type, let your compiler deduce this for you
209 @tparam EventT event type, let your compiler deduce this for you
210 @param NotificationMethod
211 Pointer to a method of a ListenerT interface.
213 Event to notify to all contained listeners
217 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
218 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
221 template< typename ListenerT
, typename EventT
>
222 inline void notifyEach( void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& ), const EventT
& Event
);
225 friend class OInterfaceIteratorHelper
;
227 bIsList == TRUE -> aData.pAsSequence of type Sequence< XInterfaceSequence >,
228 otherwise aData.pAsInterface == of type (XEventListener *)
230 detail::element_alias aData
;
231 ::osl::Mutex
& rMutex
;
232 /** TRUE -> used by an iterator. */
234 /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
237 OInterfaceContainerHelper( const OInterfaceContainerHelper
& ) SAL_THROW(());
238 OInterfaceContainerHelper
& operator = ( const OInterfaceContainerHelper
& ) SAL_THROW(());
241 Dulicate content of the conaitner and release the old one without destroying.
242 The mutex must be locked and the memberbInUse must be true.
244 void copyAndResetInUse() SAL_THROW(());
247 template< typename ListenerT
, typename EventT
>
248 class NotifySingleListener
251 typedef void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& );
252 NotificationMethod m_pMethod
;
253 const EventT
& m_rEvent
;
255 NotifySingleListener( NotificationMethod method
, const EventT
& event
) : m_pMethod( method
), m_rEvent( event
) { }
257 void operator()( const ::com::sun::star::uno::Reference
<ListenerT
>& listener
) const
259 (listener
.get()->*m_pMethod
)( m_rEvent
);
264 template <typename ListenerT
, typename FuncT
>
265 inline void OInterfaceContainerHelper::forEach( FuncT
const& func
)
267 OInterfaceIteratorHelper
iter( *this );
268 while (iter
.hasMoreElements()) {
269 ::com::sun::star::uno::Reference
<ListenerT
> const xListener(
270 iter
.next(), ::com::sun::star::uno::UNO_QUERY
);
271 if (xListener
.is()) {
272 #if defined(EXCEPTIONS_OFF)
278 catch (::com::sun::star::lang::DisposedException
const& exc
) {
279 if (exc
.Context
== xListener
)
287 template< typename ListenerT
, typename EventT
>
288 inline void OInterfaceContainerHelper::notifyEach( void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& ), const EventT
& Event
)
290 forEach
< ListenerT
, NotifySingleListener
< ListenerT
, EventT
> >( NotifySingleListener
< ListenerT
, EventT
>( NotificationMethod
, Event
) );
293 //===================================================================
295 A helper class to store interface references of different types.
297 @see OInterfaceIteratorHelper
298 @see OInterfaceContainerHelper
300 template< class key
, class hashImpl
, class equalImpl
>
301 class OMultiTypeInterfaceContainerHelperVar
304 // these are here to force memory de/allocation to sal lib.
305 inline static void * SAL_CALL
operator new( size_t nSize
) SAL_THROW(())
306 { return ::rtl_allocateMemory( nSize
); }
307 inline static void SAL_CALL
operator delete( void * pMem
) SAL_THROW(())
308 { ::rtl_freeMemory( pMem
); }
309 inline static void * SAL_CALL
operator new( size_t, void * pMem
) SAL_THROW(())
311 inline static void SAL_CALL
operator delete( void *, void * ) SAL_THROW(())
315 Create a container of interface containers.
317 @param rMutex the mutex to protect multi thread access.
318 The lifetime must be longer than the lifetime
321 inline OMultiTypeInterfaceContainerHelperVar( ::osl::Mutex
& rMutex
) SAL_THROW(());
323 Deletes all containers.
325 inline ~OMultiTypeInterfaceContainerHelperVar() SAL_THROW(());
328 Return all id's under which at least one interface is added.
330 inline ::com::sun::star::uno::Sequence
< key
> SAL_CALL
getContainedTypes() const SAL_THROW(());
333 Return the container created under this key.
334 The InterfaceContainerHelper exists until the whole MultiTypeContainer is destroyed.
335 @return the container created under this key. If the container
336 was not created, null was returned.
338 inline OInterfaceContainerHelper
* SAL_CALL
getContainer( const key
& ) const SAL_THROW(());
340 /** Inserts an element into the container with the specified key.
341 The position is not specified, thus it is not specified in which order events are fired.
344 If you add the same interface more than once, then it will be added to the elements list
345 more than once and thus if you want to remove that interface from the list, you have to call
346 removeInterface() the same number of times.
347 In the latter case, you will also get events fired more than once (if the interface is a
351 the id of the container
353 interface to be added; it is allowed, to insert null or
354 the same interface more than once
356 the new count of elements in the container
358 inline sal_Int32 SAL_CALL
addInterface(
360 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & r
)
363 /** Removes an element from the container with the specified key.
364 It uses interface equality to remove the interface.
367 the id of the container
369 interface to be removed
371 the new count of elements in the container
373 inline sal_Int32 SAL_CALL
removeInterface(
375 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & rxIFace
)
379 Call disposing on all references in the container, that
380 support XEventListener. Then clears the container.
381 @param rEvt the event object which is passed during disposing() call
383 inline void SAL_CALL
disposeAndClear( const ::com::sun::star::lang::EventObject
& rEvt
) SAL_THROW(());
385 Remove all elements of all containers. Does not delete the container.
387 inline void SAL_CALL
clear() SAL_THROW(());
391 typedef ::std::vector
< std::pair
< key
, void* > > InterfaceMap
;
392 InterfaceMap
*m_pMap
;
393 ::osl::Mutex
& rMutex
;
395 inline typename
InterfaceMap::iterator
find(const key
&rKey
) const
397 typename
InterfaceMap::iterator iter
= m_pMap
->begin();
398 typename
InterfaceMap::iterator end
= m_pMap
->end();
403 if( equal( iter
->first
, rKey
) )
410 inline OMultiTypeInterfaceContainerHelperVar( const OMultiTypeInterfaceContainerHelperVar
& ) SAL_THROW(());
411 inline OMultiTypeInterfaceContainerHelperVar
& operator = ( const OMultiTypeInterfaceContainerHelperVar
& ) SAL_THROW(());
418 This struct contains the standard variables of a broadcaster. Helper
419 classes only know a reference to this struct instead of references
420 to the four members. The access to the members must be guarded with
423 The additional template parameter keyType has been added, because gcc
424 can't compile addListener( const container::keyType &key ).
426 template < class container
, class keyType
>
427 struct OBroadcastHelperVar
429 /** The shared mutex. */
430 ::osl::Mutex
& rMutex
;
431 /** ListenerContainer class is thread safe. */
433 /** Dispose call ready. */
435 /** In dispose call. */
439 Initialize the structur. bDispose and bInDispose are set to false.
440 @param rMutex_ the mutex reference.
442 OBroadcastHelperVar( ::osl::Mutex
& rMutex_
) SAL_THROW(())
445 , bDisposed( sal_False
)
446 , bInDispose( sal_False
)
450 adds a listener threadsafe.
452 inline void addListener(
454 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> &r
)
457 ::osl::MutexGuard
guard( rMutex
);
458 OSL_ENSURE( !bInDispose
, "do not add listeners in the dispose call" );
459 OSL_ENSURE( !bDisposed
, "object is disposed" );
460 if( ! bInDispose
&& ! bDisposed
)
461 aLC
.addInterface( key
, r
);
465 removes a listener threadsafe
467 inline void removeListener(
469 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & r
)
472 ::osl::MutexGuard
guard( rMutex
);
473 OSL_ENSURE( !bDisposed
, "object is disposed" );
474 if( ! bInDispose
&& ! bDisposed
)
475 aLC
.removeInterface( key
, r
);
479 Return the container created under this key.
480 @return the container created under this key. If the container
481 was not created, null was returned. This can be used to optimize
482 performance ( construction of an event object can be avoided ).
484 inline OInterfaceContainerHelper
* SAL_CALL
getContainer( const keyType
&key
) const SAL_THROW(())
485 { return aLC
.getContainer( key
); }
488 /*------------------------------------------
490 * In general, the above templates are used with a Type as key.
491 * Therefore a default declaration is given ( OMultiTypeInterfaceContainerHelper and OBroadcastHelper )
493 *------------------------------------------*/
495 // helper function call class
498 size_t operator()(const ::com::sun::star::uno::Type
& s
) const SAL_THROW(())
499 { return (size_t) s
.getTypeName().hashCode(); }
503 /** Specialized class for key type com::sun::star::uno::Type,
504 without explicit usage of STL symbols.
506 class CPPUHELPER_DLLPUBLIC OMultiTypeInterfaceContainerHelper
509 // these are here to force memory de/allocation to sal lib.
510 inline static void * SAL_CALL
operator new( size_t nSize
) SAL_THROW(())
511 { return ::rtl_allocateMemory( nSize
); }
512 inline static void SAL_CALL
operator delete( void * pMem
) SAL_THROW(())
513 { ::rtl_freeMemory( pMem
); }
514 inline static void * SAL_CALL
operator new( size_t, void * pMem
) SAL_THROW(())
516 inline static void SAL_CALL
operator delete( void *, void * ) SAL_THROW(())
520 Create a container of interface containers.
522 @param rMutex the mutex to protect multi thread access.
523 The lifetime must be longer than the lifetime
526 OMultiTypeInterfaceContainerHelper( ::osl::Mutex
& rMutex
) SAL_THROW(());
528 Delete all containers.
530 ~OMultiTypeInterfaceContainerHelper() SAL_THROW(());
533 Return all id's under which at least one interface is added.
535 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> SAL_CALL
getContainedTypes() const SAL_THROW(());
538 Return the container created under this key.
539 @return the container created under this key. If the container
540 was not created, null was returned.
542 OInterfaceContainerHelper
* SAL_CALL
getContainer( const ::com::sun::star::uno::Type
& rKey
) const SAL_THROW(());
544 /** Inserts an element into the container with the specified key.
545 The position is not specified, thus it is not specified in which order events are fired.
548 If you add the same interface more than once, then it will be added to the elements list
549 more than once and thus if you want to remove that interface from the list, you have to call
550 removeInterface() the same number of times.
551 In the latter case, you will also get events fired more than once (if the interface is a
555 the id of the container
557 interface to be added; it is allowed, to insert null or
558 the same interface more than once
560 the new count of elements in the container
562 sal_Int32 SAL_CALL
addInterface(
563 const ::com::sun::star::uno::Type
& rKey
,
564 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & r
)
567 /** Removes an element from the container with the specified key.
568 It uses interface equality to remove the interface.
571 the id of the container
573 interface to be removed
575 the new count of elements in the container
577 sal_Int32 SAL_CALL
removeInterface(
578 const ::com::sun::star::uno::Type
& rKey
,
579 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & rxIFace
)
583 Call disposing on all object in the container that
584 support XEventListener. Than clear the container.
586 void SAL_CALL
disposeAndClear( const ::com::sun::star::lang::EventObject
& rEvt
) SAL_THROW(());
588 Remove all elements of all containers. Does not delete the container.
590 void SAL_CALL
clear() SAL_THROW(());
592 typedef ::com::sun::star::uno::Type keyType
;
595 ::osl::Mutex
& rMutex
;
597 inline OMultiTypeInterfaceContainerHelper( const OMultiTypeInterfaceContainerHelper
& ) SAL_THROW(());
598 inline OMultiTypeInterfaceContainerHelper
& operator = ( const OMultiTypeInterfaceContainerHelper
& ) SAL_THROW(());
601 typedef OBroadcastHelperVar
< OMultiTypeInterfaceContainerHelper
, OMultiTypeInterfaceContainerHelper::keyType
> OBroadcastHelper
;
607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */