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
; } } } }
51 This is here to optimise space in the common case that there are zero or one
56 std::vector
< css::uno::Reference
< css::uno::XInterface
> > *pAsVector
;
57 css::uno::XInterface
* pAsInterface
;
58 element_alias() : pAsInterface(NULL
) {}
64 class OInterfaceContainerHelper
;
66 This is the iterator of an InterfaceContainerHelper. Typically
67 one constructs an instance on the stack for one firing session.
68 It is not allowed to assign or copy an instance of this class.
70 @see OInterfaceContainerHelper
72 class CPPUHELPER_DLLPUBLIC OInterfaceIteratorHelper
76 Create an iterator over the elements of the container. The iterator
77 copies the elements of the container. A change to the container
78 during the lifetime of an iterator is allowed and does not
79 affect the iterator-instance. The iterator and the container take cares
80 themself for concurrent access, no additional guarding is necessary.
82 Remark: The copy is on demand. The iterator copy the elements only if the container
83 change the contents. It is not allowed to destroy the container as long
86 @param rCont the container of the elements.
88 OInterfaceIteratorHelper( OInterfaceContainerHelper
& rCont
);
91 Releases the connection to the container.
93 ~OInterfaceIteratorHelper();
95 /** Return true, if there are more elements in the iterator. */
96 bool SAL_CALL
hasMoreElements() const
97 { return nRemain
!= 0; }
98 /** Return the next element of the iterator. Calling this method if
99 hasMoreElements() has returned false, is an error. Cast the
100 returned pointer to the
102 css::uno::XInterface
* SAL_CALL
next();
104 /** Removes the current element (the last one returned by next())
105 from the underlying container. Calling this method before
106 next() has been called or calling it twice with no next()
107 inbetween is an error.
109 void SAL_CALL
remove();
112 OInterfaceContainerHelper
& rCont
;
115 detail::element_alias aData
;
119 OInterfaceIteratorHelper( const OInterfaceIteratorHelper
& )
120 SAL_DELETED_FUNCTION
;
121 OInterfaceIteratorHelper
& operator = ( const OInterfaceIteratorHelper
& )
122 SAL_DELETED_FUNCTION
;
127 A container of interfaces. To access the elements use an iterator.
128 This implementation is thread save.
130 @see OInterfaceIteratorHelper
132 class SAL_WARN_UNUSED CPPUHELPER_DLLPUBLIC OInterfaceContainerHelper
135 // these are here to force memory de/allocation to sal lib.
136 static void * SAL_CALL
operator new( size_t nSize
)
137 { return ::rtl_allocateMemory( nSize
); }
138 static void SAL_CALL
operator delete( void * pMem
)
139 { ::rtl_freeMemory( pMem
); }
140 static void * SAL_CALL
operator new( size_t, void * pMem
)
142 static void SAL_CALL
operator delete( void *, void * )
146 Create an interface container.
148 @param rMutex the mutex to protect multi thread access.
149 The lifetime must be longer than the lifetime
152 OInterfaceContainerHelper( ::osl::Mutex
& rMutex
);
154 Release all interfaces. All iterators must be destroyed before
155 the container is destructed.
157 ~OInterfaceContainerHelper();
159 Return the number of Elements in the container. Only useful if you have acquired
162 sal_Int32 SAL_CALL
getLength() const;
165 Return all interfaces added to this container.
167 css::uno::Sequence
< css::uno::Reference
< css::uno::XInterface
> > SAL_CALL
getElements() const;
169 /** Inserts an element into the container. The position is not specified, thus it is not
170 specified in which order events are fired.
173 If you add the same interface more than once, then it will be added to the elements list
174 more than once and thus if you want to remove that interface from the list, you have to call
175 removeInterface() the same number of times.
176 In the latter case, you will also get events fired more than once (if the interface is a
180 interface to be added; it is allowed to insert null or
181 the same interface more than once
183 the new count of elements in the container
185 sal_Int32 SAL_CALL
addInterface( const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
186 /** Removes an element from the container. It uses interface equality to remove the interface.
189 interface to be removed
191 the new count of elements in the container
193 sal_Int32 SAL_CALL
removeInterface( const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
195 Call disposing on all object in the container that
196 support XEventListener. Then clear the container.
198 void SAL_CALL
disposeAndClear( const css::lang::EventObject
& rEvt
);
200 Clears the container without calling disposing().
202 void SAL_CALL
clear();
204 /** Executes a functor for each contained listener of specified type, e.g.
205 <code>forEach<awt::XPaintListener>(...</code>.
207 If a css::lang::DisposedException occurs which relates to
208 the called listener, then that listener is removed from the container.
210 @tparam ListenerT listener type
211 @tparam FuncT unary functor type, let your compiler deduce this for you
212 @param func unary functor object expecting an argument of type
213 css::uno::Reference<ListenerT>
215 template <typename ListenerT
, typename FuncT
>
216 inline void forEach( FuncT
const& func
);
218 /** Calls a UNO listener method for each contained listener.
220 The listener method must take a single argument of type EventT,
221 and return <code>void</code>.
223 If a css::lang::DisposedException occurs which relates to
224 the called listener, then that listener is removed from the container.
226 @tparam ListenerT UNO event listener type, let your compiler deduce this for you
227 @tparam EventT event type, let your compiler deduce this for you
228 @param NotificationMethod
229 Pointer to a method of a ListenerT interface.
231 Event to notify to all contained listeners
235 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
236 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
239 template< typename ListenerT
, typename EventT
>
240 inline void notifyEach( void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& ), const EventT
& Event
);
243 friend class OInterfaceIteratorHelper
;
245 bIsList == TRUE -> aData.pAsSequence of type Sequence< XInterfaceSequence >,
246 otherwise aData.pAsInterface == of type (XEventListener *)
248 detail::element_alias aData
;
249 ::osl::Mutex
& rMutex
;
250 /** TRUE -> used by an iterator. */
252 /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
255 OInterfaceContainerHelper( const OInterfaceContainerHelper
& )
256 SAL_DELETED_FUNCTION
;
257 OInterfaceContainerHelper
& operator = ( const OInterfaceContainerHelper
& )
258 SAL_DELETED_FUNCTION
;
261 Duplicate content of the container and release the old one without destroying.
262 The mutex must be locked and the memberbInUse must be true.
264 void copyAndResetInUse();
267 template< typename ListenerT
, typename EventT
>
268 class NotifySingleListener
271 typedef void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& );
272 NotificationMethod m_pMethod
;
273 const EventT
& m_rEvent
;
275 NotifySingleListener( NotificationMethod method
, const EventT
& event
) : m_pMethod( method
), m_rEvent( event
) { }
277 void operator()( const css::uno::Reference
<ListenerT
>& listener
) const
279 (listener
.get()->*m_pMethod
)( m_rEvent
);
284 template <typename ListenerT
, typename FuncT
>
285 inline void OInterfaceContainerHelper::forEach( FuncT
const& func
)
287 OInterfaceIteratorHelper
iter( *this );
288 while (iter
.hasMoreElements()) {
289 css::uno::Reference
<ListenerT
> const xListener( iter
.next(), css::uno::UNO_QUERY
);
290 if (xListener
.is()) {
294 catch (css::lang::DisposedException
const& exc
) {
295 if (exc
.Context
== xListener
)
302 template< typename ListenerT
, typename EventT
>
303 inline void OInterfaceContainerHelper::notifyEach( void ( SAL_CALL
ListenerT::*NotificationMethod
)( const EventT
& ), const EventT
& Event
)
305 forEach
< ListenerT
, NotifySingleListener
< ListenerT
, EventT
> >( NotifySingleListener
< ListenerT
, EventT
>( NotificationMethod
, Event
) );
310 A helper class to store interface references of different types.
312 @see OInterfaceIteratorHelper
313 @see OInterfaceContainerHelper
315 template< class key
, class hashImpl
= void, class equalImpl
= std::equal_to
<key
> >
316 class OMultiTypeInterfaceContainerHelperVar
319 // these are here to force memory de/allocation to sal lib.
320 static void * SAL_CALL
operator new( size_t nSize
)
321 { return ::rtl_allocateMemory( nSize
); }
322 static void SAL_CALL
operator delete( void * pMem
)
323 { ::rtl_freeMemory( pMem
); }
324 static void * SAL_CALL
operator new( size_t, void * pMem
)
326 static void SAL_CALL
operator delete( void *, void * )
330 Create a container of interface containers.
332 @param rMutex the mutex to protect multi thread access.
333 The lifetime must be longer than the lifetime
336 inline OMultiTypeInterfaceContainerHelperVar( ::osl::Mutex
& rMutex
);
338 Deletes all containers.
340 inline ~OMultiTypeInterfaceContainerHelperVar();
343 Return all id's under which at least one interface is added.
345 inline css::uno::Sequence
< key
> SAL_CALL
getContainedTypes() const;
348 Return the container created under this key.
349 The InterfaceContainerHelper exists until the whole MultiTypeContainer is destroyed.
350 @return the container created under this key. If the container
351 was not created, null was returned.
353 inline OInterfaceContainerHelper
* SAL_CALL
getContainer( const key
& ) const;
355 /** Inserts an element into the container with the specified key.
356 The position is not specified, thus it is not specified in which order events are fired.
359 If you add the same interface more than once, then it will be added to the elements list
360 more than once and thus if you want to remove that interface from the list, you have to call
361 removeInterface() the same number of times.
362 In the latter case, you will also get events fired more than once (if the interface is a
366 the id of the container
368 interface to be added; it is allowed, to insert null or
369 the same interface more than once
371 the new count of elements in the container
373 inline sal_Int32 SAL_CALL
addInterface(
375 const css::uno::Reference
< css::uno::XInterface
> & r
);
377 /** Removes an element from the container with the specified key.
378 It uses interface equality to remove the interface.
381 the id of the container
383 interface to be removed
385 the new count of elements in the container
387 inline sal_Int32 SAL_CALL
removeInterface(
389 const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
392 Call disposing on all references in the container, that
393 support XEventListener. Then clears the container.
394 @param rEvt the event object which is passed during disposing() call
396 inline void SAL_CALL
disposeAndClear( const css::lang::EventObject
& rEvt
);
398 Remove all elements of all containers. Does not delete the container.
400 inline void SAL_CALL
clear();
404 typedef ::std::vector
< std::pair
< key
, void* > > InterfaceMap
;
405 InterfaceMap
*m_pMap
;
406 ::osl::Mutex
& rMutex
;
408 typename
InterfaceMap::iterator
find(const key
&rKey
) const
410 typename
InterfaceMap::iterator iter
= m_pMap
->begin();
411 typename
InterfaceMap::iterator end
= m_pMap
->end();
416 if( equal( iter
->first
, rKey
) )
423 OMultiTypeInterfaceContainerHelperVar( const OMultiTypeInterfaceContainerHelperVar
& ) SAL_DELETED_FUNCTION
;
424 OMultiTypeInterfaceContainerHelperVar
& operator = ( const OMultiTypeInterfaceContainerHelperVar
& ) SAL_DELETED_FUNCTION
;
431 This struct contains the standard variables of a broadcaster. Helper
432 classes only know a reference to this struct instead of references
433 to the four members. The access to the members must be guarded with
436 The additional template parameter keyType has been added, because gcc
437 can't compile addListener( const container::keyType &key ).
439 template < class container
, class keyType
>
440 struct SAL_WARN_UNUSED OBroadcastHelperVar
442 /** The shared mutex. */
443 ::osl::Mutex
& rMutex
;
444 /** ListenerContainer class is thread safe. */
446 /** Dispose call ready. */
448 /** In dispose call. */
452 Initialize the structure. bDispose and bInDispose are set to false.
453 @param rMutex_ the mutex reference.
455 OBroadcastHelperVar( ::osl::Mutex
& rMutex_
)
459 , bInDispose( false )
463 adds a listener threadsafe.
467 const css::uno::Reference
< css::uno::XInterface
> &r
)
469 ::osl::MutexGuard
guard( rMutex
);
470 OSL_ENSURE( !bInDispose
, "do not add listeners in the dispose call" );
471 OSL_ENSURE( !bDisposed
, "object is disposed" );
472 if( ! bInDispose
&& ! bDisposed
)
473 aLC
.addInterface( key
, r
);
477 removes a listener threadsafe
481 const css::uno::Reference
< css::uno::XInterface
> & r
)
483 ::osl::MutexGuard
guard( rMutex
);
484 if( ! bInDispose
&& ! bDisposed
)
485 aLC
.removeInterface( key
, r
);
489 Return the container created under this key.
490 @return the container created under this key. If the container
491 was not created, null was returned. This can be used to optimize
492 performance ( construction of an event object can be avoided ).
494 OInterfaceContainerHelper
* SAL_CALL
getContainer( const keyType
&key
) const
495 { return aLC
.getContainer( key
); }
498 /*------------------------------------------
500 * In general, the above templates are used with a Type as key.
501 * Therefore a default declaration is given ( OMultiTypeInterfaceContainerHelper and OBroadcastHelper )
503 *------------------------------------------*/
505 // helper function call class
508 size_t operator()(const css::uno::Type
& s
) const
509 { return static_cast<size_t>(s
.getTypeName().hashCode()); }
513 /** Specialized class for key type css::uno::Type,
514 without explicit usage of STL symbols.
516 class CPPUHELPER_DLLPUBLIC OMultiTypeInterfaceContainerHelper
519 // these are here to force memory de/allocation to sal lib.
520 static void * SAL_CALL
operator new( size_t nSize
)
521 { return ::rtl_allocateMemory( nSize
); }
522 static void SAL_CALL
operator delete( void * pMem
)
523 { ::rtl_freeMemory( pMem
); }
524 static void * SAL_CALL
operator new( size_t, void * pMem
)
526 static void SAL_CALL
operator delete( void *, void * )
530 Create a container of interface containers.
532 @param rMutex the mutex to protect multi thread access.
533 The lifetime must be longer than the lifetime
536 OMultiTypeInterfaceContainerHelper( ::osl::Mutex
& rMutex
);
538 Delete all containers.
540 ~OMultiTypeInterfaceContainerHelper();
543 Return all id's under which at least one interface is added.
545 css::uno::Sequence
< css::uno::Type
> SAL_CALL
getContainedTypes() const;
548 Return the container created under this key.
549 @return the container created under this key. If the container
550 was not created, null was returned.
552 OInterfaceContainerHelper
* SAL_CALL
getContainer( const css::uno::Type
& rKey
) const;
554 /** Inserts an element into the container with the specified key.
555 The position is not specified, thus it is not specified in which order events are fired.
558 If you add the same interface more than once, then it will be added to the elements list
559 more than once and thus if you want to remove that interface from the list, you have to call
560 removeInterface() the same number of times.
561 In the latter case, you will also get events fired more than once (if the interface is a
565 the id of the container
567 interface to be added; it is allowed, to insert null or
568 the same interface more than once
570 the new count of elements in the container
572 sal_Int32 SAL_CALL
addInterface(
573 const css::uno::Type
& rKey
,
574 const css::uno::Reference
< css::uno::XInterface
> & r
);
576 /** Removes an element from the container with the specified key.
577 It uses interface equality to remove the interface.
580 the id of the container
582 interface to be removed
584 the new count of elements in the container
586 sal_Int32 SAL_CALL
removeInterface(
587 const css::uno::Type
& rKey
,
588 const css::uno::Reference
< css::uno::XInterface
> & rxIFace
);
591 Call disposing on all object in the container that
592 support XEventListener. Then clear the container.
594 void SAL_CALL
disposeAndClear( const css::lang::EventObject
& rEvt
);
596 Remove all elements of all containers. Does not delete the container.
598 void SAL_CALL
clear();
600 typedef css::uno::Type keyType
;
603 ::osl::Mutex
& rMutex
;
605 OMultiTypeInterfaceContainerHelper( const OMultiTypeInterfaceContainerHelper
& ) SAL_DELETED_FUNCTION
;
606 OMultiTypeInterfaceContainerHelper
& operator = ( const OMultiTypeInterfaceContainerHelper
& ) SAL_DELETED_FUNCTION
;
609 typedef OBroadcastHelperVar
< OMultiTypeInterfaceContainerHelper
, OMultiTypeInterfaceContainerHelper::keyType
> OBroadcastHelper
;
615 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */