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"
29 #include "osl/diagnose.h"
30 #include "osl/mutex.hxx"
31 #include "rtl/alloc.h"
32 #include "com/sun/star/uno/Sequence.hxx"
33 #include "com/sun/star/lang/EventObject.hpp"
35 #include "com/sun/star/lang/DisposedException.hpp"
36 #include "cppuhelper/cppuhelperdllapi.h"
38 namespace com
{ namespace sun
{ namespace star
{ namespace uno
{ class XInterface
; } } } }
47 This is here to optimise space in the common case that there are zero or one
52 css::uno::Sequence
< css::uno::Reference
< css::uno::XInterface
> > *pAsSequence
;
53 css::uno::XInterface
* pAsInterface
;
54 element_alias() : pAsInterface(NULL
) {}
60 class OInterfaceContainerHelper
;
62 This is the iterator of a InterfaceContainerHelper. Typically
63 one constructs an instance on the stack for one firing session.
64 It is not allowed to assign or copy an instance of this class.
66 @see OInterfaceContainerHelper
68 class CPPUHELPER_DLLPUBLIC OInterfaceIteratorHelper
72 Create an iterator over the elements of the container. The iterator
73 copies the elements of the container. A change to the container
74 during the lifetime of an iterator is allowed and does not
75 affect the iterator-instance. The iterator and the container take cares
76 themself for concurrent access, no additional guarding is necessary.
78 Remark: The copy is on demand. The iterator copy the elements only if the container
79 change the contents. It is not allowed to destroy the container as long
82 @param rCont the container of the elements.
84 OInterfaceIteratorHelper( OInterfaceContainerHelper
& rCont
);
87 Releases the connection to the container.
89 ~OInterfaceIteratorHelper();
91 /** Return true, if there are more elements in the iterator. */
92 bool SAL_CALL
hasMoreElements() const
93 { return nRemain
!= 0; }
94 /** Return the next element of the iterator. Calling this method if
95 hasMoreElements() has returned false, is an error. Cast the
96 returned pointer to the
98 css::uno::XInterface
* SAL_CALL
next();
100 /** Removes the current element (the last one returned by next())
101 from the underlying container. Calling this method before
102 next() has been called or calling it twice with no next()
103 inbetween is an error.
105 void SAL_CALL
remove();
108 OInterfaceContainerHelper
& rCont
;
111 detail::element_alias aData
;
115 OInterfaceIteratorHelper( const OInterfaceIteratorHelper
& )
116 SAL_DELETED_FUNCTION
;
117 OInterfaceIteratorHelper
& operator = ( const OInterfaceIteratorHelper
& )
118 SAL_DELETED_FUNCTION
;
123 A container of interfaces. To access the elements use an iterator.
124 This implementation is thread save.
126 @see OInterfaceIteratorHelper
128 class SAL_WARN_UNUSED CPPUHELPER_DLLPUBLIC OInterfaceContainerHelper
131 // these are here to force memory de/allocation to sal lib.
132 static void * SAL_CALL
operator new( size_t nSize
)
133 { return ::rtl_allocateMemory( nSize
); }
134 static void SAL_CALL
operator delete( void * pMem
)
135 { ::rtl_freeMemory( pMem
); }
136 static void * SAL_CALL
operator new( size_t, void * pMem
)
138 static void SAL_CALL
operator delete( void *, void * )
142 Create an interface container.
144 @param rMutex the mutex to protect multi thread access.
145 The lifetime must be longer than the lifetime
148 OInterfaceContainerHelper( ::osl::Mutex
& rMutex
);
150 Release all interfaces. All iterators must be destroyed before
151 the container is destructed.
153 ~OInterfaceContainerHelper();
155 Return the number of Elements in the container. Only useful if you have acquired
158 sal_Int32 SAL_CALL
getLength() const;
161 Return all interfaces added to this container.
163 css::uno::Sequence
< css::uno::Reference
< css::uno::XInterface
> > SAL_CALL
getElements() const;
165 /** Inserts an element into the container. The position is not specified, thus it is not
166 specified in which order events are fired.
169 If you add the same interface more than once, then it will be added to the elements list
170 more than once and thus if you want to remove that interface from the list, you have to call
171 removeInterface() the same number of times.
172 In the latter case, you will also get events fired more than once (if the interface is a
176 interface to be added; it is allowed to insert null or
177 the same interface more than once
179 the new count of elements in the container
181 sal_Int32 SAL_CALL
addInterface( const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
182 /** Removes an element from the container. It uses interface equality to remove the interface.
185 interface to be removed
187 the new count of elements in the container
189 sal_Int32 SAL_CALL
removeInterface( const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
191 Call disposing on all object in the container that
192 support XEventListener. Then clear the container.
194 void SAL_CALL
disposeAndClear( const css::lang::EventObject
& rEvt
);
196 Clears the container without calling disposing().
198 void SAL_CALL
clear();
200 /** Executes a functor for each contained listener of specified type, e.g.
201 <code>forEach<awt::XPaintListener>(...</code>.
203 If a css::lang::DisposedException occurs which relates to
204 the called listener, then that listener is removed from the container.
206 @tparam ListenerT listener type
207 @tparam FuncT unary functor type, let your compiler deduce this for you
208 @param func unary functor object expecting an argument of type
209 css::uno::Reference<ListenerT>
211 template <typename ListenerT
, typename FuncT
>
212 inline void forEach( FuncT
const& func
);
214 /** Calls a UNO listener method for each contained listener.
216 The listener method must take a single argument of type EventT,
217 and return <code>void</code>.
219 If a css::lang::DisposedException occurs which relates to
220 the called listener, then that listener is removed from the container.
222 @tparam ListenerT UNO event listener type, let your compiler deduce this for you
223 @tparam EventT event type, let your compiler deduce this for you
224 @param NotificationMethod
225 Pointer to a method of a ListenerT interface.
227 Event to notify to all contained listeners
231 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
232 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
235 template< typename ListenerT
, typename EventT
>
236 inline void notifyEach( void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& ), const EventT
& Event
);
239 friend class OInterfaceIteratorHelper
;
241 bIsList == TRUE -> aData.pAsSequence of type Sequence< XInterfaceSequence >,
242 otherwise aData.pAsInterface == of type (XEventListener *)
244 detail::element_alias aData
;
245 ::osl::Mutex
& rMutex
;
246 /** TRUE -> used by an iterator. */
248 /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
251 OInterfaceContainerHelper( const OInterfaceContainerHelper
& )
252 SAL_DELETED_FUNCTION
;
253 OInterfaceContainerHelper
& operator = ( const OInterfaceContainerHelper
& )
254 SAL_DELETED_FUNCTION
;
257 Duplicate content of the container and release the old one without destroying.
258 The mutex must be locked and the memberbInUse must be true.
260 void copyAndResetInUse();
263 template< typename ListenerT
, typename EventT
>
264 class NotifySingleListener
267 typedef void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& );
268 NotificationMethod m_pMethod
;
269 const EventT
& m_rEvent
;
271 NotifySingleListener( NotificationMethod method
, const EventT
& event
) : m_pMethod( method
), m_rEvent( event
) { }
273 void operator()( const css::uno::Reference
<ListenerT
>& listener
) const
275 (listener
.get()->*m_pMethod
)( m_rEvent
);
280 template <typename ListenerT
, typename FuncT
>
281 inline void OInterfaceContainerHelper::forEach( FuncT
const& func
)
283 OInterfaceIteratorHelper
iter( *this );
284 while (iter
.hasMoreElements()) {
285 css::uno::Reference
<ListenerT
> const xListener( iter
.next(), css::uno::UNO_QUERY
);
286 if (xListener
.is()) {
290 catch (css::lang::DisposedException
const& exc
) {
291 if (exc
.Context
== xListener
)
298 template< typename ListenerT
, typename EventT
>
299 inline void OInterfaceContainerHelper::notifyEach( void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& ), const EventT
& Event
)
301 forEach
< ListenerT
, NotifySingleListener
< ListenerT
, EventT
> >( NotifySingleListener
< ListenerT
, EventT
>( NotificationMethod
, Event
) );
306 A helper class to store interface references of different types.
308 @see OInterfaceIteratorHelper
309 @see OInterfaceContainerHelper
311 template< class key
, class hashImpl
= void, class equalImpl
= std::equal_to
<key
> >
312 class OMultiTypeInterfaceContainerHelperVar
315 // these are here to force memory de/allocation to sal lib.
316 static void * SAL_CALL
operator new( size_t nSize
)
317 { return ::rtl_allocateMemory( nSize
); }
318 static void SAL_CALL
operator delete( void * pMem
)
319 { ::rtl_freeMemory( pMem
); }
320 static void * SAL_CALL
operator new( size_t, void * pMem
)
322 static void SAL_CALL
operator delete( void *, void * )
326 Create a container of interface containers.
328 @param rMutex the mutex to protect multi thread access.
329 The lifetime must be longer than the lifetime
332 inline OMultiTypeInterfaceContainerHelperVar( ::osl::Mutex
& rMutex
);
334 Deletes all containers.
336 inline ~OMultiTypeInterfaceContainerHelperVar();
339 Return all id's under which at least one interface is added.
341 inline css::uno::Sequence
< key
> SAL_CALL
getContainedTypes() const;
344 Return the container created under this key.
345 The InterfaceContainerHelper exists until the whole MultiTypeContainer is destroyed.
346 @return the container created under this key. If the container
347 was not created, null was returned.
349 inline OInterfaceContainerHelper
* SAL_CALL
getContainer( const key
& ) const;
351 /** Inserts an element into the container with the specified key.
352 The position is not specified, thus it is not specified in which order events are fired.
355 If you add the same interface more than once, then it will be added to the elements list
356 more than once and thus if you want to remove that interface from the list, you have to call
357 removeInterface() the same number of times.
358 In the latter case, you will also get events fired more than once (if the interface is a
362 the id of the container
364 interface to be added; it is allowed, to insert null or
365 the same interface more than once
367 the new count of elements in the container
369 inline sal_Int32 SAL_CALL
addInterface(
371 const css::uno::Reference
< css::uno::XInterface
> & r
);
373 /** Removes an element from the container with the specified key.
374 It uses interface equality to remove the interface.
377 the id of the container
379 interface to be removed
381 the new count of elements in the container
383 inline sal_Int32 SAL_CALL
removeInterface(
385 const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
388 Call disposing on all references in the container, that
389 support XEventListener. Then clears the container.
390 @param rEvt the event object which is passed during disposing() call
392 inline void SAL_CALL
disposeAndClear( const css::lang::EventObject
& rEvt
);
394 Remove all elements of all containers. Does not delete the container.
396 inline void SAL_CALL
clear();
400 typedef ::std::vector
< std::pair
< key
, void* > > InterfaceMap
;
401 InterfaceMap
*m_pMap
;
402 ::osl::Mutex
& rMutex
;
404 typename
InterfaceMap::iterator
find(const key
&rKey
) const
406 typename
InterfaceMap::iterator iter
= m_pMap
->begin();
407 typename
InterfaceMap::iterator end
= m_pMap
->end();
412 if( equal( iter
->first
, rKey
) )
419 OMultiTypeInterfaceContainerHelperVar( const OMultiTypeInterfaceContainerHelperVar
& ) SAL_DELETED_FUNCTION
;
420 OMultiTypeInterfaceContainerHelperVar
& operator = ( const OMultiTypeInterfaceContainerHelperVar
& ) SAL_DELETED_FUNCTION
;
427 This struct contains the standard variables of a broadcaster. Helper
428 classes only know a reference to this struct instead of references
429 to the four members. The access to the members must be guarded with
432 The additional template parameter keyType has been added, because gcc
433 can't compile addListener( const container::keyType &key ).
435 template < class container
, class keyType
>
436 struct SAL_WARN_UNUSED OBroadcastHelperVar
438 /** The shared mutex. */
439 ::osl::Mutex
& rMutex
;
440 /** ListenerContainer class is thread safe. */
442 /** Dispose call ready. */
444 /** In dispose call. */
448 Initialize the structure. bDispose and bInDispose are set to false.
449 @param rMutex_ the mutex reference.
451 OBroadcastHelperVar( ::osl::Mutex
& rMutex_
)
455 , bInDispose( false )
459 adds a listener threadsafe.
463 const css::uno::Reference
< css::uno::XInterface
> &r
)
465 ::osl::MutexGuard
guard( rMutex
);
466 OSL_ENSURE( !bInDispose
, "do not add listeners in the dispose call" );
467 OSL_ENSURE( !bDisposed
, "object is disposed" );
468 if( ! bInDispose
&& ! bDisposed
)
469 aLC
.addInterface( key
, r
);
473 removes a listener threadsafe
477 const css::uno::Reference
< css::uno::XInterface
> & r
)
479 ::osl::MutexGuard
guard( rMutex
);
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 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 css::uno::Type
& s
) const
505 { return static_cast<size_t>(s
.getTypeName().hashCode()); }
509 /** Specialized class for key type css::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 static void * SAL_CALL
operator new( size_t nSize
)
517 { return ::rtl_allocateMemory( nSize
); }
518 static void SAL_CALL
operator delete( void * pMem
)
519 { ::rtl_freeMemory( pMem
); }
520 static void * SAL_CALL
operator new( size_t, void * pMem
)
522 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 css::uno::Sequence
< css::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 css::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 css::uno::Type
& rKey
,
570 const css::uno::Reference
< css::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 css::uno::Type
& rKey
,
584 const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
587 Call disposing on all object in the container that
588 support XEventListener. Then clear the container.
590 void SAL_CALL
disposeAndClear( const css::lang::EventObject
& rEvt
);
592 Remove all elements of all containers. Does not delete the container.
594 void SAL_CALL
clear();
596 typedef css::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: */