Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / include / comphelper / interfacecontainer2.hxx
blob4439dbfc5da612f410f84b3e90f616d3506946aa
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_COMPHELPER_INTERFACECONTAINER2_H
20 #define INCLUDED_COMPHELPER_INTERFACECONTAINER2_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/uno/XInterface.hpp>
34 #include <com/sun/star/lang/EventObject.hpp>
36 #include <com/sun/star/lang/DisposedException.hpp>
37 #include <comphelper/comphelperdllapi.h>
39 /** */ //for docpp
40 namespace comphelper
43 namespace detail {
45 /**
46 This is here to optimise space in the common case that there are zero or one
47 listeners.
49 union element_alias2
51 std::vector< css::uno::Reference< css::uno::XInterface > > *pAsVector;
52 css::uno::XInterface * pAsInterface;
53 element_alias2() : pAsInterface(nullptr) {}
59 class OInterfaceContainerHelper2;
60 /**
61 This is the iterator of a InterfaceContainerHelper. Typically
62 one constructs an instance on the stack for one firing session.
63 It is not allowed to assign or copy an instance of this class.
65 @see OInterfaceContainerHelper
67 class COMPHELPER_DLLPUBLIC OInterfaceIteratorHelper2
69 public:
70 /**
71 Create an iterator over the elements of the container. The iterator
72 copies the elements of the container. A change to the container
73 during the lifetime of an iterator is allowed and does not
74 affect the iterator-instance. The iterator and the container take cares
75 themself for concurrent access, no additional guarding is necessary.
77 Remark: The copy is on demand. The iterator copy the elements only if the container
78 change the contents. It is not allowed to destroy the container as long
79 as an iterator exist.
81 @param rCont the container of the elements.
83 OInterfaceIteratorHelper2( OInterfaceContainerHelper2 & rCont );
85 /**
86 Releases the connection to the container.
88 ~OInterfaceIteratorHelper2();
90 /** Return true, if there are more elements in the iterator. */
91 bool SAL_CALL hasMoreElements() const
92 { return nRemain != 0; }
93 /** Return the next element of the iterator. Calling this method if
94 hasMoreElements() has returned false, is an error. Cast the
95 returned pointer to the
97 css::uno::XInterface * SAL_CALL next();
99 /** Removes the current element (the last one returned by next())
100 from the underlying container. Calling this method before
101 next() has been called or calling it twice with no next()
102 inbetween is an error.
104 void SAL_CALL remove();
106 private:
107 OInterfaceContainerHelper2 & rCont;
108 bool bIsList;
109 detail::element_alias2 aData;
110 sal_Int32 nRemain;
112 OInterfaceIteratorHelper2( const OInterfaceIteratorHelper2 & )
113 SAL_DELETED_FUNCTION;
114 OInterfaceIteratorHelper2 & operator = ( const OInterfaceIteratorHelper2 & )
115 SAL_DELETED_FUNCTION;
120 A container of interfaces. To access the elements use an iterator.
121 This implementation is thread save.
123 @see OInterfaceIteratorHelper
125 class COMPHELPER_DLLPUBLIC OInterfaceContainerHelper2
127 public:
128 // these are here to force memory de/allocation to sal lib.
129 static void * SAL_CALL operator new( size_t nSize )
130 { return ::rtl_allocateMemory( nSize ); }
131 static void SAL_CALL operator delete( void * pMem )
132 { ::rtl_freeMemory( pMem ); }
133 static void * SAL_CALL operator new( size_t, void * pMem )
134 { return pMem; }
135 static void SAL_CALL operator delete( void *, void * )
139 Create an interface container.
141 @param rMutex the mutex to protect multi thread access.
142 The lifetime must be longer than the lifetime
143 of this object.
145 OInterfaceContainerHelper2( ::osl::Mutex & rMutex );
147 Release all interfaces. All iterators must be destroyed before
148 the container is destructed.
150 ~OInterfaceContainerHelper2();
152 Return the number of Elements in the container. Only useful if you have acquired
153 the mutex.
155 sal_Int32 SAL_CALL getLength() const;
158 Return all interfaces added to this container.
160 std::vector< css::uno::Reference< css::uno::XInterface > > SAL_CALL getElements() const;
162 /** Inserts an element into the container. The position is not specified, thus it is not
163 specified in which order events are fired.
165 @attention
166 If you add the same interface more than once, then it will be added to the elements list
167 more than once and thus if you want to remove that interface from the list, you have to call
168 removeInterface() the same number of times.
169 In the latter case, you will also get events fired more than once (if the interface is a
170 listener interface).
172 @param rxIFace
173 interface to be added; it is allowed to insert null or
174 the same interface more than once
175 @return
176 the new count of elements in the container
178 sal_Int32 SAL_CALL addInterface( const css::uno::Reference< css::uno::XInterface > & rxIFace );
179 /** Removes an element from the container. It uses interface equality to remove the interface.
181 @param rxIFace
182 interface to be removed
183 @return
184 the new count of elements in the container
186 sal_Int32 SAL_CALL removeInterface( const css::uno::Reference< css::uno::XInterface > & rxIFace );
188 Call disposing on all object in the container that
189 support XEventListener. Than clear the container.
191 void SAL_CALL disposeAndClear( const css::lang::EventObject & rEvt );
193 Clears the container without calling disposing().
195 void SAL_CALL clear();
197 /** Executes a functor for each contained listener of specified type, e.g.
198 <code>forEach<awt::XPaintListener>(...</code>.
200 If a css::lang::DisposedException occurs which relates to
201 the called listener, then that listener is removed from the container.
203 @tparam ListenerT listener type
204 @tparam FuncT unary functor type, let your compiler deduce this for you
205 @param func unary functor object expecting an argument of type
206 css::uno::Reference<ListenerT>
208 template <typename ListenerT, typename FuncT>
209 inline void forEach( FuncT const& func );
211 /** Calls a UNO listener method for each contained listener.
213 The listener method must take a single argument of type EventT,
214 and return <code>void</code>.
216 If a css::lang::DisposedException occurs which relates to
217 the called listener, then that listener is removed from the container.
219 @tparam ListenerT UNO event listener type, let your compiler deduce this for you
220 @tparam EventT event type, let your compiler deduce this for you
221 @param NotificationMethod
222 Pointer to a method of a ListenerT interface.
223 @param Event
224 Event to notify to all contained listeners
226 Example:
227 @code
228 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
229 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
230 @endcode
232 template< typename ListenerT, typename EventT >
233 inline void notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event );
235 private:
236 friend class OInterfaceIteratorHelper2;
238 bIsList == TRUE -> aData.pAsVector of type vector< XInterfaceSequence >,
239 otherwise aData.pAsInterface == of type (XEventListener *)
241 detail::element_alias2 aData;
242 ::osl::Mutex & rMutex;
243 /** TRUE -> used by an iterator. */
244 bool bInUse;
245 /** TRUE -> aData.pAsVector is of type Sequence< XInterfaceSequence >. */
246 bool bIsList;
248 OInterfaceContainerHelper2( const OInterfaceContainerHelper2 & )
249 SAL_DELETED_FUNCTION;
250 OInterfaceContainerHelper2 & operator = ( const OInterfaceContainerHelper2 & )
251 SAL_DELETED_FUNCTION;
254 Duplicate content of the container and release the old one without destroying.
255 The mutex must be locked and the memberbInUse must be true.
257 void copyAndResetInUse();
259 private:
260 template< typename ListenerT, typename EventT >
261 class NotifySingleListener
263 private:
264 typedef void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& );
265 NotificationMethod m_pMethod;
266 const EventT& m_rEvent;
267 public:
268 NotifySingleListener( NotificationMethod method, const EventT& event ) : m_pMethod( method ), m_rEvent( event ) { }
270 void operator()( const css::uno::Reference<ListenerT>& listener ) const
272 (listener.get()->*m_pMethod)( m_rEvent );
277 template <typename ListenerT, typename FuncT>
278 inline void OInterfaceContainerHelper2::forEach( FuncT const& func )
280 OInterfaceIteratorHelper2 iter( *this );
281 while (iter.hasMoreElements()) {
282 css::uno::Reference<ListenerT> const xListener( iter.next(), css::uno::UNO_QUERY );
283 if (xListener.is()) {
284 try {
285 func( xListener );
287 catch (css::lang::DisposedException const& exc) {
288 if (exc.Context == xListener)
289 iter.remove();
295 template< typename ListenerT, typename EventT >
296 inline void OInterfaceContainerHelper2::notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event )
298 forEach< ListenerT, NotifySingleListener< ListenerT, EventT > >( NotifySingleListener< ListenerT, EventT >( NotificationMethod, Event ) );
302 #endif
304 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */