Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / include / cppuhelper / interfacecontainer.h
blobd901b2db3cccfe8e82b883fe84204373571b518e
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 .
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"
28 #include <cstddef>
29 #include <functional>
30 #include <vector>
31 #include <utility>
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; } } } }
44 namespace cppu
47 namespace detail {
49 /**
50 This is here to optimise space in the common case that there are zero or one
51 listeners.
53 union element_alias
55 std::vector< css::uno::Reference< css::uno::XInterface > > *pAsVector;
56 css::uno::XInterface * pAsInterface;
57 element_alias() : pAsInterface(NULL) {}
63 class OInterfaceContainerHelper;
64 /**
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
73 public:
74 /**
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
83 as an iterator exist.
85 @param rCont the container of the elements.
87 OInterfaceIteratorHelper( OInterfaceContainerHelper & rCont );
89 /**
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();
110 private:
111 OInterfaceContainerHelper & rCont;
112 sal_Bool bIsList;
114 detail::element_alias aData;
116 sal_Int32 nRemain;
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
133 public:
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 )
140 { return 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
149 of this object.
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
159 the mutex.
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.
171 @attention
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
176 listener interface).
178 @param rxIFace
179 interface to be added; it is allowed to insert null or
180 the same interface more than once
181 @return
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.
187 @param rxIFace
188 interface to be removed
189 @return
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.
229 @param Event
230 Event to notify to all contained listeners
232 Example:
233 @code
234 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
235 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
236 @endcode
238 template< typename ListenerT, typename EventT >
239 inline void notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event );
241 private:
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. */
250 sal_Bool bInUse;
251 /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
252 sal_Bool bIsList;
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();
265 private:
266 template< typename ListenerT, typename EventT >
267 class NotifySingleListener
269 private:
270 typedef void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& );
271 NotificationMethod m_pMethod;
272 const EventT& m_rEvent;
273 public:
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()) {
290 try {
291 func( xListener );
293 catch (css::lang::DisposedException const& exc) {
294 if (exc.Context == xListener)
295 iter.remove();
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
317 public:
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 )
324 { return 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
333 of this object.
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.
357 @attention
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
362 listener interface).
364 @param rKey
365 the id of the container
366 @param r
367 interface to be added; it is allowed, to insert null or
368 the same interface more than once
369 @return
370 the new count of elements in the container
372 inline sal_Int32 SAL_CALL addInterface(
373 const key & rKey,
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.
379 @param rKey
380 the id of the container
381 @param rxIFace
382 interface to be removed
383 @return
384 the new count of elements in the container
386 inline sal_Int32 SAL_CALL removeInterface(
387 const key & rKey,
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();
401 typedef key keyType;
402 private:
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();
412 while( iter != end )
414 equalImpl equal;
415 if( equal( iter->first, rKey ) )
416 break;
417 ++iter;
419 return iter;
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
433 rMutex.
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. */
444 container aLC;
445 /** Dispose call ready. */
446 sal_Bool bDisposed;
447 /** In dispose call. */
448 sal_Bool bInDispose;
451 Initialize the structure. bDispose and bInDispose are set to false.
452 @param rMutex_ the mutex reference.
454 OBroadcastHelperVar( ::osl::Mutex & rMutex_ )
455 : rMutex( rMutex_ )
456 , aLC( rMutex_ )
457 , bDisposed( false )
458 , bInDispose( false )
462 adds a listener threadsafe.
464 void addListener(
465 const keyType &key,
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
478 void removeListener(
479 const keyType &key,
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 ).
492 ***/
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
505 struct hashType_Impl
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
517 public:
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 )
524 { return 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
533 of this object.
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.
556 @attention
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
561 listener interface).
563 @param rKey
564 the id of the container
565 @param r
566 interface to be added; it is allowed, to insert null or
567 the same interface more than once
568 @return
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.
578 @param rKey
579 the id of the container
580 @param rxIFace
581 interface to be removed
582 @return
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;
600 private:
601 void * m_pMap;
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;
612 #endif
614 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */