1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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_INTERFACECONTAINER3_H
20 #define INCLUDED_COMPHELPER_INTERFACECONTAINER3_H
22 #include <sal/config.h>
24 #include <com/sun/star/lang/EventObject.hpp>
25 #include <com/sun/star/lang/DisposedException.hpp>
26 #include <o3tl/cow_wrapper.hxx>
29 namespace com::sun::star::uno
41 template <class ListenerT
> class OInterfaceContainerHelper3
;
43 This is the iterator of an OInterfaceContainerHelper3. Typically
44 one constructs an instance on the stack for one firing session.
45 It is not allowed to assign or copy an instance of this class.
47 @tparam ListenerT UNO event listener type
48 @see OInterfaceContainerHelper3
50 template <class ListenerT
> class OInterfaceIteratorHelper3
54 Create an iterator over the elements of the container. The iterator
55 copies the elements of the container. A change to the container
56 during the lifetime of an iterator is allowed and does not
57 affect the iterator-instance. The iterator and the container take cares
58 themself for concurrent access, no additional guarding is necessary.
60 Remark: The copy is on demand. The iterator copy the elements only if the container
61 change the contents...
63 @param rCont the container of the elements.
65 OInterfaceIteratorHelper3(OInterfaceContainerHelper3
<ListenerT
>& rCont_
)
67 , maData(rCont
.maData
)
68 , nRemain(maData
->size())
72 /** Return true, if there are more elements in the iterator. */
73 bool hasMoreElements() const { return nRemain
!= 0; }
74 /** Return the next element of the iterator. Calling this method if
75 hasMoreElements() has returned false, is an error.
77 css::uno::Reference
<ListenerT
> const& next();
79 /** Removes the current element (the last one returned by next())
80 from the underlying container. Calling this method before
81 next() has been called or calling it twice with no next()
82 in between is an error.
87 OInterfaceContainerHelper3
<ListenerT
>& rCont
;
88 o3tl::cow_wrapper
<std::vector
<css::uno::Reference
<ListenerT
>>,
89 o3tl::ThreadSafeRefCountingPolicy
>
93 OInterfaceIteratorHelper3(const OInterfaceIteratorHelper3
&) = delete;
94 OInterfaceIteratorHelper3
& operator=(const OInterfaceIteratorHelper3
&) = delete;
97 template <class ListenerT
>
98 const css::uno::Reference
<ListenerT
>& OInterfaceIteratorHelper3
<ListenerT
>::next()
101 return (*maData
)[nRemain
];
104 template <class ListenerT
> void OInterfaceIteratorHelper3
<ListenerT
>::remove()
106 rCont
.removeInterface((*maData
)[nRemain
]);
110 A container of interfaces. To access the elements use an iterator.
111 This implementation is thread-safe.
113 This is a copy of the code at include/comphelper/interfacecontainer2.hxx,
114 except that it is templatized on the type of the listener, which allows
115 some parts of the code to avoid doing an UNO_QUERY that can be expensive
118 @tparam ListenerT UNO event listener type
119 @see OInterfaceIteratorHelper
121 template <class ListenerT
> class OInterfaceContainerHelper3
125 Create an interface container.
127 @param rMutex the mutex to protect multi thread access.
128 The lifetime must be longer than the lifetime
131 OInterfaceContainerHelper3(::osl::Mutex
& rMutex_
)
136 Return the number of Elements in the container. Only useful if you have acquired
139 sal_Int32
getLength() const;
142 Return all interfaces added to this container.
144 std::vector
<css::uno::Reference
<ListenerT
>> getElements() const;
146 /** Inserts an element into the container. The position is not specified, thus it is not
147 specified in which order events are fired.
150 If you add the same interface more than once, then it will be added to the elements list
151 more than once and thus if you want to remove that interface from the list, you have to call
152 removeInterface() the same number of times.
153 In the latter case, you will also get events fired more than once (if the interface is a
157 interface to be added; it is allowed to insert
158 the same interface more than once
160 the new count of elements in the container
162 sal_Int32
addInterface(const css::uno::Reference
<ListenerT
>& rxIFace
);
163 /** Removes an element from the container. It uses interface equality to remove the interface.
166 interface to be removed
168 the new count of elements in the container
170 sal_Int32
removeInterface(const css::uno::Reference
<ListenerT
>& rxIFace
);
172 Call disposing on all object in the container that
173 support XEventListener. Then clear the container.
175 void disposeAndClear(const css::lang::EventObject
& rEvt
);
177 Clears the container without calling disposing().
181 /** Executes a functor for each contained listener of specified type, e.g.
182 <code>forEach<awt::XPaintListener>(...</code>.
184 If a css::lang::DisposedException occurs which relates to
185 the called listener, then that listener is removed from the container.
187 @tparam FuncT unary functor type, let your compiler deduce this for you
188 @param func unary functor object expecting an argument of type
189 css::uno::Reference<ListenerT>
191 template <typename FuncT
> inline void forEach(FuncT
const& func
);
193 /** Calls a UNO listener method for each contained listener.
195 The listener method must take a single argument of type EventT,
196 and return <code>void</code>.
198 If a css::lang::DisposedException occurs which relates to
199 the called listener, then that listener is removed from the container.
201 @tparam EventT event type, let your compiler deduce this for you
202 @param NotificationMethod
203 Pointer to a method of a ListenerT interface.
205 Event to notify to all contained listeners
209 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
210 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
213 template <typename EventT
>
214 inline void notifyEach(void (SAL_CALL
ListenerT::*NotificationMethod
)(const EventT
&),
215 const EventT
& Event
);
218 friend class OInterfaceIteratorHelper3
<ListenerT
>;
219 o3tl::cow_wrapper
<std::vector
<css::uno::Reference
<ListenerT
>>,
220 o3tl::ThreadSafeRefCountingPolicy
>
222 ::osl::Mutex
& rMutex
;
223 OInterfaceContainerHelper3(const OInterfaceContainerHelper3
&) = delete;
224 OInterfaceContainerHelper3
& operator=(const OInterfaceContainerHelper3
&) = delete;
227 template <typename EventT
> class NotifySingleListener
230 typedef void (SAL_CALL
ListenerT::*NotificationMethod
)(const EventT
&);
231 NotificationMethod
const m_pMethod
;
232 const EventT
& m_rEvent
;
235 NotifySingleListener(NotificationMethod method
, const EventT
& event
)
241 void operator()(const css::uno::Reference
<ListenerT
>& listener
) const
243 (listener
.get()->*m_pMethod
)(m_rEvent
);
249 template <typename FuncT
>
250 inline void OInterfaceContainerHelper3
<T
>::forEach(FuncT
const& func
)
252 OInterfaceIteratorHelper3
<T
> iter(*this);
253 while (iter
.hasMoreElements())
255 auto xListener
= iter
.next();
260 catch (css::lang::DisposedException
const& exc
)
262 if (exc
.Context
== xListener
)
268 template <class ListenerT
>
269 template <typename EventT
>
270 inline void OInterfaceContainerHelper3
<ListenerT
>::notifyEach(
271 void (SAL_CALL
ListenerT::*NotificationMethod
)(const EventT
&), const EventT
& Event
)
273 forEach
<NotifySingleListener
<EventT
>>(NotifySingleListener
<EventT
>(NotificationMethod
, Event
));
276 template <class ListenerT
> sal_Int32 OInterfaceContainerHelper3
<ListenerT
>::getLength() const
278 osl::MutexGuard
aGuard(rMutex
);
279 return maData
->size();
282 template <class ListenerT
>
283 std::vector
<css::uno::Reference
<ListenerT
>>
284 OInterfaceContainerHelper3
<ListenerT
>::getElements() const
286 std::vector
<css::uno::Reference
<ListenerT
>> rVec
;
287 osl::MutexGuard
aGuard(rMutex
);
292 template <class ListenerT
>
294 OInterfaceContainerHelper3
<ListenerT
>::addInterface(const css::uno::Reference
<ListenerT
>& rListener
)
296 assert(rListener
.is());
297 osl::MutexGuard
aGuard(rMutex
);
299 maData
->push_back(rListener
);
300 return maData
->size();
303 template <class ListenerT
>
304 sal_Int32 OInterfaceContainerHelper3
<ListenerT
>::removeInterface(
305 const css::uno::Reference
<ListenerT
>& rListener
)
307 assert(rListener
.is());
308 osl::MutexGuard
aGuard(rMutex
);
310 // It is not valid to compare the pointer directly, but it's faster.
311 auto it
= std::find_if(maData
->begin(), maData
->end(),
312 [&rListener
](const css::uno::Reference
<css::uno::XInterface
>& rItem
) {
313 return rItem
.get() == rListener
.get();
316 // interface not found, use the correct compare method
317 if (it
== maData
->end())
318 it
= std::find(maData
->begin(), maData
->end(), rListener
);
320 if (it
!= maData
->end())
323 return maData
->size();
326 template <class ListenerT
>
327 void OInterfaceContainerHelper3
<ListenerT
>::disposeAndClear(const css::lang::EventObject
& rEvt
)
329 osl::ClearableMutexGuard
aGuard(rMutex
);
330 OInterfaceIteratorHelper3
<ListenerT
> aIt(*this);
333 while (aIt
.hasMoreElements())
337 aIt
.next()->disposing(rEvt
);
339 catch (css::uno::RuntimeException
&)
341 // be robust, if e.g. a remote bridge has disposed already.
342 // there is no way to delegate the error to the caller :o(.
347 template <class ListenerT
> void OInterfaceContainerHelper3
<ListenerT
>::clear()
349 osl::MutexGuard
aGuard(rMutex
);
355 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */