bump product version to 6.3.0.0.beta1
[LibreOffice.git] / include / cppuhelper / interfacecontainer.h
blob2d56568c9da5bd3242afff55842cce789f196001
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 INCLUDED_CPPUHELPER_INTERFACECONTAINER_H
20 #define INCLUDED_CPPUHELPER_INTERFACECONTAINER_H
22 #include "sal/config.h"
24 #include <cstddef>
25 #include <functional>
26 #include <vector>
27 #include <utility>
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; } } } }
40 /** */ //for docpp
41 namespace cppu
44 namespace detail {
46 /**
47 This is here to optimise space in the common case that there are zero or one
48 listeners.
50 union element_alias
52 css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > *pAsSequence;
53 css::uno::XInterface * pAsInterface;
54 element_alias() : pAsInterface(NULL) {}
60 class OInterfaceContainerHelper;
61 /**
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
70 public:
71 /**
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
80 as an iterator exist.
82 @param rCont the container of the elements.
84 OInterfaceIteratorHelper( OInterfaceContainerHelper & rCont );
86 /**
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();
107 private:
108 OInterfaceContainerHelper & rCont;
109 sal_Bool bIsList;
111 detail::element_alias aData;
113 sal_Int32 nRemain;
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
130 public:
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 )
137 { return 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
146 of this object.
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
156 the mutex.
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.
168 @attention
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
173 listener interface).
175 @param rxIFace
176 interface to be added; it is allowed to insert null or
177 the same interface more than once
178 @return
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.
184 @param rxIFace
185 interface to be removed
186 @return
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.
226 @param Event
227 Event to notify to all contained listeners
229 Example:
230 @code
231 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
232 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
233 @endcode
235 template< typename ListenerT, typename EventT >
236 inline void notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event );
238 private:
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. */
247 sal_Bool bInUse;
248 /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
249 sal_Bool bIsList;
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();
262 private:
263 template< typename ListenerT, typename EventT >
264 class NotifySingleListener
266 private:
267 typedef void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& );
268 NotificationMethod m_pMethod;
269 const EventT& m_rEvent;
270 public:
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()) {
287 try {
288 func( xListener );
290 catch (css::lang::DisposedException const& exc) {
291 if (exc.Context == xListener)
292 iter.remove();
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
314 public:
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 )
321 { return 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
330 of this object.
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.
354 @attention
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
359 listener interface).
361 @param rKey
362 the id of the container
363 @param r
364 interface to be added; it is allowed, to insert null or
365 the same interface more than once
366 @return
367 the new count of elements in the container
369 inline sal_Int32 SAL_CALL addInterface(
370 const key & rKey,
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.
376 @param rKey
377 the id of the container
378 @param rxIFace
379 interface to be removed
380 @return
381 the new count of elements in the container
383 inline sal_Int32 SAL_CALL removeInterface(
384 const key & rKey,
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();
398 typedef key keyType;
399 private:
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();
409 while( iter != end )
411 equalImpl equal;
412 if( equal( iter->first, rKey ) )
413 break;
414 ++iter;
416 return iter;
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
430 rMutex.
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. */
441 container aLC;
442 /** Dispose call ready. */
443 sal_Bool bDisposed;
444 /** In dispose call. */
445 sal_Bool bInDispose;
448 Initialize the structure. bDispose and bInDispose are set to false.
449 @param rMutex_ the mutex reference.
451 OBroadcastHelperVar( ::osl::Mutex & rMutex_ )
452 : rMutex( rMutex_ )
453 , aLC( rMutex_ )
454 , bDisposed( false )
455 , bInDispose( false )
459 adds a listener threadsafe.
461 void addListener(
462 const keyType &key,
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
475 void removeListener(
476 const keyType &key,
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 ).
489 ***/
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
502 struct hashType_Impl
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
514 public:
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 )
521 { return 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
530 of this object.
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.
553 @attention
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
558 listener interface).
560 @param rKey
561 the id of the container
562 @param r
563 interface to be added; it is allowed, to insert null or
564 the same interface more than once
565 @return
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.
575 @param rKey
576 the id of the container
577 @param rxIFace
578 interface to be removed
579 @return
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;
597 private:
598 void * m_pMap;
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;
609 #endif
611 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */