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 INCLUDED_CPPUHELPER_INTERFACECONTAINER_H
20 #define INCLUDED_CPPUHELPER_INTERFACECONTAINER_H
22 #include <sal/config.h>
28 #include <osl/diagnose.h>
29 #include <osl/mutex.hxx>
30 #include <rtl/alloc.h>
31 #include <com/sun/star/uno/Sequence.hxx>
32 #include <com/sun/star/uno/XInterface.hpp>
33 #include <com/sun/star/lang/EventObject.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 #include <cppuhelper/cppuhelperdllapi.h>
45 This is here to optimise space in the common case that there are zero or one
50 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> > *pAsSequence
;
51 ::com::sun::star::uno::XInterface
* pAsInterface
;
52 element_alias() : pAsInterface(0) {}
58 class OInterfaceContainerHelper
;
60 This is the iterator of a InterfaceContainerHelper. Typically
61 one constructs an instance on the stack for one firing session.
62 It is not allowed to assign or copy an instance of this class.
64 @see OInterfaceContainerHelper
66 class CPPUHELPER_DLLPUBLIC OInterfaceIteratorHelper
70 Create an iterator over the elements of the container. The iterator
71 copies the elements of the conatainer. A change to the container
72 during the lifetime of an iterator is allowed and does not
73 affect the iterator-instance. The iterator and the container take cares
74 themself for concurrent access, no additional guarding is necessary.
76 Remark: The copy is on demand. The iterator copy the elements only if the container
77 change the contents. It is not allowed to destroy the container as long
80 @param rCont the container of the elements.
82 OInterfaceIteratorHelper( OInterfaceContainerHelper
& rCont
);
85 Releases the connection to the container.
87 ~OInterfaceIteratorHelper();
89 /** Return true, if there are more elements in the iterator. */
90 bool SAL_CALL
hasMoreElements() const
91 { return nRemain
!= 0; }
92 /** Return the next element of the iterator. Calling this method if
93 hasMoreElements() has returned false, is an error. Cast the
94 returned pointer to the
96 ::com::sun::star::uno::XInterface
* SAL_CALL
next();
98 /** Removes the current element (the last one returned by next())
99 from the underlying container. Calling this method before
100 next() has been called or calling it twice with no next()
101 inbetween is an error.
103 void SAL_CALL
remove();
106 OInterfaceContainerHelper
& rCont
;
109 detail::element_alias aData
;
113 OInterfaceIteratorHelper( const OInterfaceIteratorHelper
& )
114 SAL_DELETED_FUNCTION
;
115 OInterfaceIteratorHelper
& operator = ( const OInterfaceIteratorHelper
& )
116 SAL_DELETED_FUNCTION
;
121 A container of interfaces. To access the elements use an iterator.
122 This implementation is thread save.
124 @see OInterfaceIteratorHelper
126 class CPPUHELPER_DLLPUBLIC OInterfaceContainerHelper
129 // these are here to force memory de/allocation to sal lib.
130 inline static void * SAL_CALL
operator new( size_t nSize
)
131 { return ::rtl_allocateMemory( nSize
); }
132 inline static void SAL_CALL
operator delete( void * pMem
)
133 { ::rtl_freeMemory( pMem
); }
134 inline static void * SAL_CALL
operator new( size_t, void * pMem
)
136 inline static void SAL_CALL
operator delete( void *, void * )
140 Create an interface container.
142 @param rMutex the mutex to protect multi thread access.
143 The lifetime must be longer than the lifetime
146 OInterfaceContainerHelper( ::osl::Mutex
& rMutex
);
148 Release all interfaces. All iterators must be destroyed before
149 the container is destructed.
151 ~OInterfaceContainerHelper();
153 Return the number of Elements in the container. Only useful if you have acquired
156 sal_Int32 SAL_CALL
getLength() const;
159 Return all interfaces added to this container.
161 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> > SAL_CALL
getElements() const;
163 /** Inserts an element into the container. The position is not specified, thus it is not
164 specified in which order events are fired.
167 If you add the same interface more than once, then it will be added to the elements list
168 more than once and thus if you want to remove that interface from the list, you have to call
169 removeInterface() the same number of times.
170 In the latter case, you will also get events fired more than once (if the interface is a
174 interface to be added; it is allowed to insert null or
175 the same interface more than once
177 the new count of elements in the container
179 sal_Int32 SAL_CALL
addInterface( const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & rxIFace
);
180 /** Removes an element from the container. It uses interface equality to remove the interface.
183 interface to be removed
185 the new count of elements in the container
187 sal_Int32 SAL_CALL
removeInterface( const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & rxIFace
);
189 Call disposing on all object in the container that
190 support XEventListener. Than clear the container.
192 void SAL_CALL
disposeAndClear( const ::com::sun::star::lang::EventObject
& rEvt
);
194 Clears the container without calling disposing().
196 void SAL_CALL
clear();
198 /** Executes a functor for each contained listener of specified type, e.g.
199 <code>forEach<awt::XPaintListener>(...</code>.
201 If a com::sun::star::lang::DisposedException occurs which relates to
202 the called listener, then that listener is removed from the container.
204 @tparam ListenerT listener type
205 @tparam FuncT unary functor type, let your compiler deduce this for you
206 @param func unary functor object expecting an argument of type
207 com::sun::star::uno::Reference<ListenerT>
209 template <typename ListenerT
, typename FuncT
>
210 inline void forEach( FuncT
const& func
);
212 /** Calls a UNO listener method for each contained listener.
214 The listener method must take a single argument of type EventT,
215 and return <code>void</code>.
217 If a com::sun::star::lang::DisposedException occurs which relates to
218 the called listener, then that listener is removed from the container.
220 @tparam ListenerT UNO event listener type, let your compiler deduce this for you
221 @tparam EventT event type, let your compiler deduce this for you
222 @param NotificationMethod
223 Pointer to a method of a ListenerT interface.
225 Event to notify to all contained listeners
229 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
230 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
233 template< typename ListenerT
, typename EventT
>
234 inline void notifyEach( void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& ), const EventT
& Event
);
237 friend class OInterfaceIteratorHelper
;
239 bIsList == TRUE -> aData.pAsSequence of type Sequence< XInterfaceSequence >,
240 otherwise aData.pAsInterface == of type (XEventListener *)
242 detail::element_alias aData
;
243 ::osl::Mutex
& rMutex
;
244 /** TRUE -> used by an iterator. */
246 /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
249 OInterfaceContainerHelper( const OInterfaceContainerHelper
& )
250 SAL_DELETED_FUNCTION
;
251 OInterfaceContainerHelper
& operator = ( const OInterfaceContainerHelper
& )
252 SAL_DELETED_FUNCTION
;
255 Dulicate content of the conaitner and release the old one without destroying.
256 The mutex must be locked and the memberbInUse must be true.
258 void copyAndResetInUse();
261 template< typename ListenerT
, typename EventT
>
262 class NotifySingleListener
265 typedef void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& );
266 NotificationMethod m_pMethod
;
267 const EventT
& m_rEvent
;
269 NotifySingleListener( NotificationMethod method
, const EventT
& event
) : m_pMethod( method
), m_rEvent( event
) { }
271 void operator()( const ::com::sun::star::uno::Reference
<ListenerT
>& listener
) const
273 (listener
.get()->*m_pMethod
)( m_rEvent
);
278 template <typename ListenerT
, typename FuncT
>
279 inline void OInterfaceContainerHelper::forEach( FuncT
const& func
)
281 OInterfaceIteratorHelper
iter( *this );
282 while (iter
.hasMoreElements()) {
283 ::com::sun::star::uno::Reference
<ListenerT
> const xListener(
284 iter
.next(), ::com::sun::star::uno::UNO_QUERY
);
285 if (xListener
.is()) {
289 catch (::com::sun::star::lang::DisposedException
const& exc
) {
290 if (exc
.Context
== xListener
)
297 template< typename ListenerT
, typename EventT
>
298 inline void OInterfaceContainerHelper::notifyEach( void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& ), const EventT
& Event
)
300 forEach
< ListenerT
, NotifySingleListener
< ListenerT
, EventT
> >( NotifySingleListener
< ListenerT
, EventT
>( NotificationMethod
, Event
) );
305 A helper class to store interface references of different types.
307 @see OInterfaceIteratorHelper
308 @see OInterfaceContainerHelper
310 template< class key
, class hashImpl
= void, class equalImpl
= std::equal_to
<key
> >
311 class OMultiTypeInterfaceContainerHelperVar
314 // these are here to force memory de/allocation to sal lib.
315 inline static void * SAL_CALL
operator new( size_t nSize
)
316 { return ::rtl_allocateMemory( nSize
); }
317 inline static void SAL_CALL
operator delete( void * pMem
)
318 { ::rtl_freeMemory( pMem
); }
319 inline static void * SAL_CALL
operator new( size_t, void * pMem
)
321 inline static void SAL_CALL
operator delete( void *, void * )
325 Create a container of interface containers.
327 @param rMutex the mutex to protect multi thread access.
328 The lifetime must be longer than the lifetime
331 inline OMultiTypeInterfaceContainerHelperVar( ::osl::Mutex
& rMutex
);
333 Deletes all containers.
335 inline ~OMultiTypeInterfaceContainerHelperVar();
338 Return all id's under which at least one interface is added.
340 inline ::com::sun::star::uno::Sequence
< key
> SAL_CALL
getContainedTypes() const;
343 Return the container created under this key.
344 The InterfaceContainerHelper exists until the whole MultiTypeContainer is destroyed.
345 @return the container created under this key. If the container
346 was not created, null was returned.
348 inline OInterfaceContainerHelper
* SAL_CALL
getContainer( const key
& ) const;
350 /** Inserts an element into the container with the specified key.
351 The position is not specified, thus it is not specified in which order events are fired.
354 If you add the same interface more than once, then it will be added to the elements list
355 more than once and thus if you want to remove that interface from the list, you have to call
356 removeInterface() the same number of times.
357 In the latter case, you will also get events fired more than once (if the interface is a
361 the id of the container
363 interface to be added; it is allowed, to insert null or
364 the same interface more than once
366 the new count of elements in the container
368 inline sal_Int32 SAL_CALL
addInterface(
370 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & r
);
372 /** Removes an element from the container with the specified key.
373 It uses interface equality to remove the interface.
376 the id of the container
378 interface to be removed
380 the new count of elements in the container
382 inline sal_Int32 SAL_CALL
removeInterface(
384 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & rxIFace
);
387 Call disposing on all references in the container, that
388 support XEventListener. Then clears the container.
389 @param rEvt the event object which is passed during disposing() call
391 inline void SAL_CALL
disposeAndClear( const ::com::sun::star::lang::EventObject
& rEvt
);
393 Remove all elements of all containers. Does not delete the container.
395 inline void SAL_CALL
clear();
399 typedef ::std::vector
< std::pair
< key
, void* > > InterfaceMap
;
400 InterfaceMap
*m_pMap
;
401 ::osl::Mutex
& rMutex
;
403 inline typename
InterfaceMap::iterator
find(const key
&rKey
) const
405 typename
InterfaceMap::iterator iter
= m_pMap
->begin();
406 typename
InterfaceMap::iterator end
= m_pMap
->end();
411 if( equal( iter
->first
, rKey
) )
418 OMultiTypeInterfaceContainerHelperVar( const OMultiTypeInterfaceContainerHelperVar
& ) SAL_DELETED_FUNCTION
;
419 OMultiTypeInterfaceContainerHelperVar
& operator = ( const OMultiTypeInterfaceContainerHelperVar
& ) SAL_DELETED_FUNCTION
;
426 This struct contains the standard variables of a broadcaster. Helper
427 classes only know a reference to this struct instead of references
428 to the four members. The access to the members must be guarded with
431 The additional template parameter keyType has been added, because gcc
432 can't compile addListener( const container::keyType &key ).
434 template < class container
, class keyType
>
435 struct OBroadcastHelperVar
437 /** The shared mutex. */
438 ::osl::Mutex
& rMutex
;
439 /** ListenerContainer class is thread safe. */
441 /** Dispose call ready. */
443 /** In dispose call. */
447 Initialize the structure. bDispose and bInDispose are set to false.
448 @param rMutex_ the mutex reference.
450 OBroadcastHelperVar( ::osl::Mutex
& rMutex_
)
453 , bDisposed( sal_False
)
454 , bInDispose( sal_False
)
458 adds a listener threadsafe.
460 inline void addListener(
462 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> &r
)
464 ::osl::MutexGuard
guard( rMutex
);
465 OSL_ENSURE( !bInDispose
, "do not add listeners in the dispose call" );
466 OSL_ENSURE( !bDisposed
, "object is disposed" );
467 if( ! bInDispose
&& ! bDisposed
)
468 aLC
.addInterface( key
, r
);
472 removes a listener threadsafe
474 inline void removeListener(
476 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & r
)
478 ::osl::MutexGuard
guard( rMutex
);
479 OSL_ENSURE( !bDisposed
, "object is disposed" );
480 if( ! bInDispose
&& ! bDisposed
)
481 aLC
.removeInterface( key
, r
);
485 Return the container created under this key.
486 @return the container created under this key. If the container
487 was not created, null was returned. This can be used to optimize
488 performance ( construction of an event object can be avoided ).
490 inline OInterfaceContainerHelper
* SAL_CALL
getContainer( const keyType
&key
) const
491 { return aLC
.getContainer( key
); }
494 /*------------------------------------------
496 * In general, the above templates are used with a Type as key.
497 * Therefore a default declaration is given ( OMultiTypeInterfaceContainerHelper and OBroadcastHelper )
499 *------------------------------------------*/
501 // helper function call class
504 size_t operator()(const ::com::sun::star::uno::Type
& s
) const
505 { return (size_t) s
.getTypeName().hashCode(); }
509 /** Specialized class for key type com::sun::star::uno::Type,
510 without explicit usage of STL symbols.
512 class CPPUHELPER_DLLPUBLIC OMultiTypeInterfaceContainerHelper
515 // these are here to force memory de/allocation to sal lib.
516 inline static void * SAL_CALL
operator new( size_t nSize
)
517 { return ::rtl_allocateMemory( nSize
); }
518 inline static void SAL_CALL
operator delete( void * pMem
)
519 { ::rtl_freeMemory( pMem
); }
520 inline static void * SAL_CALL
operator new( size_t, void * pMem
)
522 inline static void SAL_CALL
operator delete( void *, void * )
526 Create a container of interface containers.
528 @param rMutex the mutex to protect multi thread access.
529 The lifetime must be longer than the lifetime
532 OMultiTypeInterfaceContainerHelper( ::osl::Mutex
& rMutex
);
534 Delete all containers.
536 ~OMultiTypeInterfaceContainerHelper();
539 Return all id's under which at least one interface is added.
541 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> SAL_CALL
getContainedTypes() const;
544 Return the container created under this key.
545 @return the container created under this key. If the container
546 was not created, null was returned.
548 OInterfaceContainerHelper
* SAL_CALL
getContainer( const ::com::sun::star::uno::Type
& rKey
) const;
550 /** Inserts an element into the container with the specified key.
551 The position is not specified, thus it is not specified in which order events are fired.
554 If you add the same interface more than once, then it will be added to the elements list
555 more than once and thus if you want to remove that interface from the list, you have to call
556 removeInterface() the same number of times.
557 In the latter case, you will also get events fired more than once (if the interface is a
561 the id of the container
563 interface to be added; it is allowed, to insert null or
564 the same interface more than once
566 the new count of elements in the container
568 sal_Int32 SAL_CALL
addInterface(
569 const ::com::sun::star::uno::Type
& rKey
,
570 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & r
);
572 /** Removes an element from the container with the specified key.
573 It uses interface equality to remove the interface.
576 the id of the container
578 interface to be removed
580 the new count of elements in the container
582 sal_Int32 SAL_CALL
removeInterface(
583 const ::com::sun::star::uno::Type
& rKey
,
584 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> & rxIFace
);
587 Call disposing on all object in the container that
588 support XEventListener. Than clear the container.
590 void SAL_CALL
disposeAndClear( const ::com::sun::star::lang::EventObject
& rEvt
);
592 Remove all elements of all containers. Does not delete the container.
594 void SAL_CALL
clear();
596 typedef ::com::sun::star::uno::Type keyType
;
599 ::osl::Mutex
& rMutex
;
601 OMultiTypeInterfaceContainerHelper( const OMultiTypeInterfaceContainerHelper
& ) SAL_DELETED_FUNCTION
;
602 OMultiTypeInterfaceContainerHelper
& operator = ( const OMultiTypeInterfaceContainerHelper
& ) SAL_DELETED_FUNCTION
;
605 typedef OBroadcastHelperVar
< OMultiTypeInterfaceContainerHelper
, OMultiTypeInterfaceContainerHelper::keyType
> OBroadcastHelper
;
611 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */