make ValueTransfer easier to understand
[LibreOffice.git] / include / cppuhelper / interfacecontainer.h
blob520998d4cd927d7859ef22693cbaa19da3eb61b3
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 /** */ //for docpp
45 namespace cppu
48 namespace detail {
50 /**
51 This is here to optimise space in the common case that there are zero or one
52 listeners.
54 union element_alias
56 std::vector< css::uno::Reference< css::uno::XInterface > > *pAsVector;
57 css::uno::XInterface * pAsInterface;
58 element_alias() : pAsInterface(NULL) {}
64 class OInterfaceContainerHelper;
65 /**
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
74 public:
75 /**
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
84 as an iterator exist.
86 @param rCont the container of the elements.
88 OInterfaceIteratorHelper( OInterfaceContainerHelper & rCont );
90 /**
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();
111 private:
112 OInterfaceContainerHelper & rCont;
113 sal_Bool bIsList;
115 detail::element_alias aData;
117 sal_Int32 nRemain;
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
134 public:
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 )
141 { return 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
150 of this object.
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
160 the mutex.
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.
172 @attention
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
177 listener interface).
179 @param rxIFace
180 interface to be added; it is allowed to insert null or
181 the same interface more than once
182 @return
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.
188 @param rxIFace
189 interface to be removed
190 @return
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.
230 @param Event
231 Event to notify to all contained listeners
233 Example:
234 @code
235 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
236 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
237 @endcode
239 template< typename ListenerT, typename EventT >
240 inline void notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event );
242 private:
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. */
251 sal_Bool bInUse;
252 /** TRUE -> aData.pAsSequence is of type Sequence< XInterfaceSequence >. */
253 sal_Bool bIsList;
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();
266 private:
267 template< typename ListenerT, typename EventT >
268 class NotifySingleListener
270 private:
271 typedef void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& );
272 NotificationMethod m_pMethod;
273 const EventT& m_rEvent;
274 public:
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()) {
291 try {
292 func( xListener );
294 catch (css::lang::DisposedException const& exc) {
295 if (exc.Context == xListener)
296 iter.remove();
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
318 public:
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 )
325 { return 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
334 of this object.
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.
358 @attention
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
363 listener interface).
365 @param rKey
366 the id of the container
367 @param r
368 interface to be added; it is allowed, to insert null or
369 the same interface more than once
370 @return
371 the new count of elements in the container
373 inline sal_Int32 SAL_CALL addInterface(
374 const key & rKey,
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.
380 @param rKey
381 the id of the container
382 @param rxIFace
383 interface to be removed
384 @return
385 the new count of elements in the container
387 inline sal_Int32 SAL_CALL removeInterface(
388 const key & rKey,
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();
402 typedef key keyType;
403 private:
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();
413 while( iter != end )
415 equalImpl equal;
416 if( equal( iter->first, rKey ) )
417 break;
418 ++iter;
420 return iter;
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
434 rMutex.
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. */
445 container aLC;
446 /** Dispose call ready. */
447 sal_Bool bDisposed;
448 /** In dispose call. */
449 sal_Bool bInDispose;
452 Initialize the structure. bDispose and bInDispose are set to false.
453 @param rMutex_ the mutex reference.
455 OBroadcastHelperVar( ::osl::Mutex & rMutex_ )
456 : rMutex( rMutex_ )
457 , aLC( rMutex_ )
458 , bDisposed( false )
459 , bInDispose( false )
463 adds a listener threadsafe.
465 void addListener(
466 const keyType &key,
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
479 void removeListener(
480 const keyType &key,
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 ).
493 ***/
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
506 struct hashType_Impl
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
518 public:
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 )
525 { return 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
534 of this object.
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.
557 @attention
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
562 listener interface).
564 @param rKey
565 the id of the container
566 @param r
567 interface to be added; it is allowed, to insert null or
568 the same interface more than once
569 @return
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.
579 @param rKey
580 the id of the container
581 @param rxIFace
582 interface to be removed
583 @return
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;
601 private:
602 void * m_pMap;
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;
613 #endif
615 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */