update credits
[LibreOffice.git] / include / cppuhelper / interfacecontainer.h
blob774f900a8b2612e708f4592d4a2d4b1f1cbe444c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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_
22 #include <vector>
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"
32 /** */ //for docpp
33 namespace cppu
36 namespace detail {
38 union element_alias
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;
49 /**
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
58 public:
59 /**
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
68 as an iterator exist.
70 @param rCont the container of the elements.
72 OInterfaceIteratorHelper( OInterfaceContainerHelper & rCont ) SAL_THROW(());
74 /**
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(());
95 private:
96 OInterfaceContainerHelper & rCont;
97 sal_Bool bIsList;
99 detail::element_alias aData;
101 sal_Int32 nRemain;
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
116 public:
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(())
123 { return pMem; }
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
132 of this object.
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
142 the mutex.
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.
154 @attention
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
159 listener interface).
161 @param rxIFace
162 interface to be added; it is allowed to insert null or
163 the same interface more than once
164 @return
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.
170 @param rxIFace
171 interface to be removed
172 @return
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.
212 @param Event
213 Event to notify to all contained listeners
215 Example:
216 @code
217 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
218 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
219 @endcode
221 template< typename ListenerT, typename EventT >
222 inline void notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event );
224 private:
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. */
233 sal_Bool bInUse;
234 /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
235 sal_Bool bIsList;
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(());
246 private:
247 template< typename ListenerT, typename EventT >
248 class NotifySingleListener
250 private:
251 typedef void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& );
252 NotificationMethod m_pMethod;
253 const EventT& m_rEvent;
254 public:
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)
273 func( xListener );
274 #else
275 try {
276 func( xListener );
278 catch (::com::sun::star::lang::DisposedException const& exc) {
279 if (exc.Context == xListener)
280 iter.remove();
282 #endif
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
303 public:
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(())
310 { return pMem; }
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
319 of this object.
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.
343 @attention
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
348 listener interface).
350 @param rKey
351 the id of the container
352 @param r
353 interface to be added; it is allowed, to insert null or
354 the same interface more than once
355 @return
356 the new count of elements in the container
358 inline sal_Int32 SAL_CALL addInterface(
359 const key & rKey,
360 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & r )
361 SAL_THROW(());
363 /** Removes an element from the container with the specified key.
364 It uses interface equality to remove the interface.
366 @param rKey
367 the id of the container
368 @param rxIFace
369 interface to be removed
370 @return
371 the new count of elements in the container
373 inline sal_Int32 SAL_CALL removeInterface(
374 const key & rKey,
375 const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & rxIFace )
376 SAL_THROW(());
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(());
389 typedef key keyType;
390 private:
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();
400 while( iter != end )
402 equalImpl equal;
403 if( equal( iter->first, rKey ) )
404 break;
405 iter++;
407 return iter;
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
421 rMutex.
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. */
432 container aLC;
433 /** Dispose call ready. */
434 sal_Bool bDisposed;
435 /** In dispose call. */
436 sal_Bool bInDispose;
439 Initialize the structur. bDispose and bInDispose are set to false.
440 @param rMutex_ the mutex reference.
442 OBroadcastHelperVar( ::osl::Mutex & rMutex_ ) SAL_THROW(())
443 : rMutex( rMutex_ )
444 , aLC( rMutex_ )
445 , bDisposed( sal_False )
446 , bInDispose( sal_False )
450 adds a listener threadsafe.
452 inline void addListener(
453 const keyType &key,
454 const ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface > &r )
455 SAL_THROW(())
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(
468 const keyType &key,
469 const ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface > & r )
470 SAL_THROW(())
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 ).
483 ***/
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
496 struct hashType_Impl
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
508 public:
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(())
515 { return pMem; }
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
524 of this object.
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.
547 @attention
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
552 listener interface).
554 @param rKey
555 the id of the container
556 @param r
557 interface to be added; it is allowed, to insert null or
558 the same interface more than once
559 @return
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 )
565 SAL_THROW(());
567 /** Removes an element from the container with the specified key.
568 It uses interface equality to remove the interface.
570 @param rKey
571 the id of the container
572 @param rxIFace
573 interface to be removed
574 @return
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 )
580 SAL_THROW(());
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;
593 private:
594 void *m_pMap;
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;
605 #endif
607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */