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 .
21 * This file is part of LibreOffice published API.
23 #ifndef INCLUDED_CPPUHELPER_INTERFACECONTAINER_H
24 #define INCLUDED_CPPUHELPER_INTERFACECONTAINER_H
26 #include "sal/config.h"
33 #include "osl/diagnose.h"
34 #include "osl/mutex.hxx"
35 #include "rtl/alloc.h"
36 #include "com/sun/star/uno/Sequence.hxx"
37 #include "com/sun/star/lang/EventObject.hpp"
39 #include "com/sun/star/lang/DisposedException.hpp"
40 #include "cppuhelper/cppuhelperdllapi.h"
42 namespace com
{ namespace sun
{ namespace star
{ namespace uno
{ class XInterface
; } } } }
50 This is here to optimise space in the common case that there are zero or one
55 std::vector
< css::uno::Reference
< css::uno::XInterface
> > *pAsVector
;
56 css::uno::XInterface
* pAsInterface
;
57 element_alias() : pAsInterface(NULL
) {}
63 class OInterfaceContainerHelper
;
65 This is the iterator of an InterfaceContainerHelper. Typically
66 one constructs an instance on the stack for one firing session.
67 It is not allowed to assign or copy an instance of this class.
69 @see OInterfaceContainerHelper
71 class CPPUHELPER_DLLPUBLIC OInterfaceIteratorHelper
75 Create an iterator over the elements of the container. The iterator
76 copies the elements of the container. A change to the container
77 during the lifetime of an iterator is allowed and does not
78 affect the iterator-instance. The iterator and the container take cares
79 themself for concurrent access, no additional guarding is necessary.
81 Remark: The copy is on demand. The iterator copy the elements only if the container
82 change the contents. It is not allowed to destroy the container as long
85 @param rCont the container of the elements.
87 OInterfaceIteratorHelper( OInterfaceContainerHelper
& rCont
);
90 Releases the connection to the container.
92 ~OInterfaceIteratorHelper();
94 /** Return true, if there are more elements in the iterator. */
95 bool SAL_CALL
hasMoreElements() const
96 { return nRemain
!= 0; }
97 /** Return the next element of the iterator. Calling this method if
98 hasMoreElements() has returned false, is an error. Cast the
99 returned pointer to the
101 css::uno::XInterface
* SAL_CALL
next();
103 /** Removes the current element (the last one returned by next())
104 from the underlying container. Calling this method before
105 next() has been called or calling it twice with no next()
106 inbetween is an error.
108 void SAL_CALL
remove();
111 OInterfaceContainerHelper
& rCont
;
114 detail::element_alias aData
;
118 OInterfaceIteratorHelper( const OInterfaceIteratorHelper
& )
119 SAL_DELETED_FUNCTION
;
120 OInterfaceIteratorHelper
& operator = ( const OInterfaceIteratorHelper
& )
121 SAL_DELETED_FUNCTION
;
126 A container of interfaces. To access the elements use an iterator.
127 This implementation is thread save.
129 @see OInterfaceIteratorHelper
131 class SAL_WARN_UNUSED CPPUHELPER_DLLPUBLIC OInterfaceContainerHelper
134 // these are here to force memory de/allocation to sal lib.
135 static void * SAL_CALL
operator new( size_t nSize
)
136 { return ::rtl_allocateMemory( nSize
); }
137 static void SAL_CALL
operator delete( void * pMem
)
138 { ::rtl_freeMemory( pMem
); }
139 static void * SAL_CALL
operator new( size_t, void * pMem
)
141 static void SAL_CALL
operator delete( void *, void * )
145 Create an interface container.
147 @param rMutex the mutex to protect multi thread access.
148 The lifetime must be longer than the lifetime
151 OInterfaceContainerHelper( ::osl::Mutex
& rMutex
);
153 Release all interfaces. All iterators must be destroyed before
154 the container is destructed.
156 ~OInterfaceContainerHelper();
158 Return the number of Elements in the container. Only useful if you have acquired
161 sal_Int32 SAL_CALL
getLength() const;
164 Return all interfaces added to this container.
166 css::uno::Sequence
< css::uno::Reference
< css::uno::XInterface
> > SAL_CALL
getElements() const;
168 /** Inserts an element into the container. The position is not specified, thus it is not
169 specified in which order events are fired.
172 If you add the same interface more than once, then it will be added to the elements list
173 more than once and thus if you want to remove that interface from the list, you have to call
174 removeInterface() the same number of times.
175 In the latter case, you will also get events fired more than once (if the interface is a
179 interface to be added; it is allowed to insert null or
180 the same interface more than once
182 the new count of elements in the container
184 sal_Int32 SAL_CALL
addInterface( const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
185 /** Removes an element from the container. It uses interface equality to remove the interface.
188 interface to be removed
190 the new count of elements in the container
192 sal_Int32 SAL_CALL
removeInterface( const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
194 Call disposing on all object in the container that
195 support XEventListener. Then clear the container.
197 void SAL_CALL
disposeAndClear( const css::lang::EventObject
& rEvt
);
199 Clears the container without calling disposing().
201 void SAL_CALL
clear();
203 /** Executes a functor for each contained listener of specified type, e.g.
204 <code>forEach<awt::XPaintListener>(...</code>.
206 If a css::lang::DisposedException occurs which relates to
207 the called listener, then that listener is removed from the container.
209 @tparam ListenerT listener type
210 @tparam FuncT unary functor type, let your compiler deduce this for you
211 @param func unary functor object expecting an argument of type
212 css::uno::Reference<ListenerT>
214 template <typename ListenerT
, typename FuncT
>
215 inline void forEach( FuncT
const& func
);
217 /** Calls a UNO listener method for each contained listener.
219 The listener method must take a single argument of type EventT,
220 and return <code>void</code>.
222 If a css::lang::DisposedException occurs which relates to
223 the called listener, then that listener is removed from the container.
225 @tparam ListenerT UNO event listener type, let your compiler deduce this for you
226 @tparam EventT event type, let your compiler deduce this for you
227 @param NotificationMethod
228 Pointer to a method of a ListenerT interface.
230 Event to notify to all contained listeners
234 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
235 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
238 template< typename ListenerT
, typename EventT
>
239 inline void notifyEach( void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& ), const EventT
& Event
);
242 friend class OInterfaceIteratorHelper
;
244 bIsList == TRUE -> aData.pAsSequence of type Sequence< XInterfaceSequence >,
245 otherwise aData.pAsInterface == of type (XEventListener *)
247 detail::element_alias aData
;
248 ::osl::Mutex
& rMutex
;
249 /** TRUE -> used by an iterator. */
251 /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
254 OInterfaceContainerHelper( const OInterfaceContainerHelper
& )
255 SAL_DELETED_FUNCTION
;
256 OInterfaceContainerHelper
& operator = ( const OInterfaceContainerHelper
& )
257 SAL_DELETED_FUNCTION
;
260 Duplicate content of the container and release the old one without destroying.
261 The mutex must be locked and the memberbInUse must be true.
263 void copyAndResetInUse();
266 template< typename ListenerT
, typename EventT
>
267 class NotifySingleListener
270 typedef void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& );
271 NotificationMethod m_pMethod
;
272 const EventT
& m_rEvent
;
274 NotifySingleListener( NotificationMethod method
, const EventT
& event
) : m_pMethod( method
), m_rEvent( event
) { }
276 void operator()( const css::uno::Reference
<ListenerT
>& listener
) const
278 (listener
.get()->*m_pMethod
)( m_rEvent
);
283 template <typename ListenerT
, typename FuncT
>
284 inline void OInterfaceContainerHelper::forEach( FuncT
const& func
)
286 OInterfaceIteratorHelper
iter( *this );
287 while (iter
.hasMoreElements()) {
288 css::uno::Reference
<ListenerT
> const xListener( iter
.next(), css::uno::UNO_QUERY
);
289 if (xListener
.is()) {
293 catch (css::lang::DisposedException
const& exc
) {
294 if (exc
.Context
== xListener
)
301 template< typename ListenerT
, typename EventT
>
302 inline void OInterfaceContainerHelper::notifyEach( void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& ), const EventT
& Event
)
304 forEach
< ListenerT
, NotifySingleListener
< ListenerT
, EventT
> >( NotifySingleListener
< ListenerT
, EventT
>( NotificationMethod
, Event
) );
309 A helper class to store interface references of different types.
311 @see OInterfaceIteratorHelper
312 @see OInterfaceContainerHelper
314 template< class key
, class hashImpl
= void, class equalImpl
= std::equal_to
<key
> >
315 class OMultiTypeInterfaceContainerHelperVar
318 // these are here to force memory de/allocation to sal lib.
319 static void * SAL_CALL
operator new( size_t nSize
)
320 { return ::rtl_allocateMemory( nSize
); }
321 static void SAL_CALL
operator delete( void * pMem
)
322 { ::rtl_freeMemory( pMem
); }
323 static void * SAL_CALL
operator new( size_t, void * pMem
)
325 static void SAL_CALL
operator delete( void *, void * )
329 Create a container of interface containers.
331 @param rMutex the mutex to protect multi thread access.
332 The lifetime must be longer than the lifetime
335 inline OMultiTypeInterfaceContainerHelperVar( ::osl::Mutex
& rMutex
);
337 Deletes all containers.
339 inline ~OMultiTypeInterfaceContainerHelperVar();
342 Return all id's under which at least one interface is added.
344 inline css::uno::Sequence
< key
> SAL_CALL
getContainedTypes() const;
347 Return the container created under this key.
348 The InterfaceContainerHelper exists until the whole MultiTypeContainer is destroyed.
349 @return the container created under this key. If the container
350 was not created, null was returned.
352 inline OInterfaceContainerHelper
* SAL_CALL
getContainer( const key
& ) const;
354 /** Inserts an element into the container with the specified key.
355 The position is not specified, thus it is not specified in which order events are fired.
358 If you add the same interface more than once, then it will be added to the elements list
359 more than once and thus if you want to remove that interface from the list, you have to call
360 removeInterface() the same number of times.
361 In the latter case, you will also get events fired more than once (if the interface is a
365 the id of the container
367 interface to be added; it is allowed, to insert null or
368 the same interface more than once
370 the new count of elements in the container
372 inline sal_Int32 SAL_CALL
addInterface(
374 const css::uno::Reference
< css::uno::XInterface
> & r
);
376 /** Removes an element from the container with the specified key.
377 It uses interface equality to remove the interface.
380 the id of the container
382 interface to be removed
384 the new count of elements in the container
386 inline sal_Int32 SAL_CALL
removeInterface(
388 const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
391 Call disposing on all references in the container, that
392 support XEventListener. Then clears the container.
393 @param rEvt the event object which is passed during disposing() call
395 inline void SAL_CALL
disposeAndClear( const css::lang::EventObject
& rEvt
);
397 Remove all elements of all containers. Does not delete the container.
399 inline void SAL_CALL
clear();
403 typedef ::std::vector
< std::pair
< key
, void* > > InterfaceMap
;
404 InterfaceMap
*m_pMap
;
405 ::osl::Mutex
& rMutex
;
407 typename
InterfaceMap::iterator
find(const key
&rKey
) const
409 typename
InterfaceMap::iterator iter
= m_pMap
->begin();
410 typename
InterfaceMap::iterator end
= m_pMap
->end();
415 if( equal( iter
->first
, rKey
) )
422 OMultiTypeInterfaceContainerHelperVar( const OMultiTypeInterfaceContainerHelperVar
& ) SAL_DELETED_FUNCTION
;
423 OMultiTypeInterfaceContainerHelperVar
& operator = ( const OMultiTypeInterfaceContainerHelperVar
& ) SAL_DELETED_FUNCTION
;
430 This struct contains the standard variables of a broadcaster. Helper
431 classes only know a reference to this struct instead of references
432 to the four members. The access to the members must be guarded with
435 The additional template parameter keyType has been added, because gcc
436 can't compile addListener( const container::keyType &key ).
438 template < class container
, class keyType
>
439 struct SAL_WARN_UNUSED OBroadcastHelperVar
441 /** The shared mutex. */
442 ::osl::Mutex
& rMutex
;
443 /** ListenerContainer class is thread safe. */
445 /** Dispose call ready. */
447 /** In dispose call. */
451 Initialize the structure. bDispose and bInDispose are set to false.
452 @param rMutex_ the mutex reference.
454 OBroadcastHelperVar( ::osl::Mutex
& rMutex_
)
458 , bInDispose( false )
462 adds a listener threadsafe.
466 const css::uno::Reference
< css::uno::XInterface
> &r
)
468 ::osl::MutexGuard
guard( rMutex
);
469 OSL_ENSURE( !bInDispose
, "do not add listeners in the dispose call" );
470 OSL_ENSURE( !bDisposed
, "object is disposed" );
471 if( ! bInDispose
&& ! bDisposed
)
472 aLC
.addInterface( key
, r
);
476 removes a listener threadsafe
480 const css::uno::Reference
< css::uno::XInterface
> & r
)
482 ::osl::MutexGuard
guard( rMutex
);
483 if( ! bInDispose
&& ! bDisposed
)
484 aLC
.removeInterface( key
, r
);
488 Return the container created under this key.
489 @return the container created under this key. If the container
490 was not created, null was returned. This can be used to optimize
491 performance ( construction of an event object can be avoided ).
493 OInterfaceContainerHelper
* SAL_CALL
getContainer( const keyType
&key
) const
494 { return aLC
.getContainer( key
); }
497 /*------------------------------------------
499 * In general, the above templates are used with a Type as key.
500 * Therefore a default declaration is given ( OMultiTypeInterfaceContainerHelper and OBroadcastHelper )
502 *------------------------------------------*/
504 // helper function call class
507 size_t operator()(const css::uno::Type
& s
) const
508 { return static_cast<size_t>(s
.getTypeName().hashCode()); }
512 /** Specialized class for key type css::uno::Type,
513 without explicit usage of STL symbols.
515 class CPPUHELPER_DLLPUBLIC OMultiTypeInterfaceContainerHelper
518 // these are here to force memory de/allocation to sal lib.
519 static void * SAL_CALL
operator new( size_t nSize
)
520 { return ::rtl_allocateMemory( nSize
); }
521 static void SAL_CALL
operator delete( void * pMem
)
522 { ::rtl_freeMemory( pMem
); }
523 static void * SAL_CALL
operator new( size_t, void * pMem
)
525 static void SAL_CALL
operator delete( void *, void * )
529 Create a container of interface containers.
531 @param rMutex the mutex to protect multi thread access.
532 The lifetime must be longer than the lifetime
535 OMultiTypeInterfaceContainerHelper( ::osl::Mutex
& rMutex
);
537 Delete all containers.
539 ~OMultiTypeInterfaceContainerHelper();
542 Return all id's under which at least one interface is added.
544 css::uno::Sequence
< css::uno::Type
> SAL_CALL
getContainedTypes() const;
547 Return the container created under this key.
548 @return the container created under this key. If the container
549 was not created, null was returned.
551 OInterfaceContainerHelper
* SAL_CALL
getContainer( const css::uno::Type
& rKey
) const;
553 /** Inserts an element into the container with the specified key.
554 The position is not specified, thus it is not specified in which order events are fired.
557 If you add the same interface more than once, then it will be added to the elements list
558 more than once and thus if you want to remove that interface from the list, you have to call
559 removeInterface() the same number of times.
560 In the latter case, you will also get events fired more than once (if the interface is a
564 the id of the container
566 interface to be added; it is allowed, to insert null or
567 the same interface more than once
569 the new count of elements in the container
571 sal_Int32 SAL_CALL
addInterface(
572 const css::uno::Type
& rKey
,
573 const css::uno::Reference
< css::uno::XInterface
> & r
);
575 /** Removes an element from the container with the specified key.
576 It uses interface equality to remove the interface.
579 the id of the container
581 interface to be removed
583 the new count of elements in the container
585 sal_Int32 SAL_CALL
removeInterface(
586 const css::uno::Type
& rKey
,
587 const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
590 Call disposing on all object in the container that
591 support XEventListener. Then clear the container.
593 void SAL_CALL
disposeAndClear( const css::lang::EventObject
& rEvt
);
595 Remove all elements of all containers. Does not delete the container.
597 void SAL_CALL
clear();
599 typedef css::uno::Type keyType
;
602 ::osl::Mutex
& rMutex
;
604 OMultiTypeInterfaceContainerHelper( const OMultiTypeInterfaceContainerHelper
& ) SAL_DELETED_FUNCTION
;
605 OMultiTypeInterfaceContainerHelper
& operator = ( const OMultiTypeInterfaceContainerHelper
& ) SAL_DELETED_FUNCTION
;
608 typedef OBroadcastHelperVar
< OMultiTypeInterfaceContainerHelper
, OMultiTypeInterfaceContainerHelper::keyType
> OBroadcastHelper
;
614 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */