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 .
21 #include <sal/config.h>
23 #include <com/sun/star/lang/EventObject.hpp>
24 #include <com/sun/star/lang/DisposedException.hpp>
25 #include <o3tl/cow_wrapper.hxx>
28 namespace com::sun::star::uno
39 template <class ListenerT
> class OInterfaceContainerHelper3
;
41 This is the iterator of an OInterfaceContainerHelper3. Typically
42 one constructs an instance on the stack for one firing session.
43 It is not allowed to assign or copy an instance of this class.
45 @tparam ListenerT UNO event listener type
46 @see OInterfaceContainerHelper3
48 template <class ListenerT
> class OInterfaceIteratorHelper3
52 Create an iterator over the elements of the container. The iterator
53 copies the elements of the container. A change to the container
54 during the lifetime of an iterator is allowed and does not
55 affect the iterator-instance. The iterator and the container take cares
56 themself for concurrent access, no additional guarding is necessary.
58 Remark: The copy is on demand. The iterator copy the elements only if the container
59 change the contents...
61 @param rCont the container of the elements.
63 OInterfaceIteratorHelper3(OInterfaceContainerHelper3
<ListenerT
>& rCont_
)
65 , maData(rCont
.maData
)
66 // const_cast so we don't trigger make_unique via o3tl::cow_wrapper::operator->
67 , nRemain(std::as_const(maData
)->size())
71 /** Return true, if there are more elements in the iterator. */
72 bool hasMoreElements() const { return nRemain
!= 0; }
73 /** Return the next element of the iterator. Calling this method if
74 hasMoreElements() has returned false, is an error.
76 css::uno::Reference
<ListenerT
> const& next();
78 /** Removes the current element (the last one returned by next())
79 from the underlying container. Calling this method before
80 next() has been called or calling it twice with no next()
81 in between is an error.
86 OInterfaceContainerHelper3
<ListenerT
>& rCont
;
87 o3tl::cow_wrapper
<std::vector
<css::uno::Reference
<ListenerT
>>,
88 o3tl::ThreadSafeRefCountingPolicy
>
92 OInterfaceIteratorHelper3(const OInterfaceIteratorHelper3
&) = delete;
93 OInterfaceIteratorHelper3
& operator=(const OInterfaceIteratorHelper3
&) = delete;
96 template <class ListenerT
>
97 const css::uno::Reference
<ListenerT
>& OInterfaceIteratorHelper3
<ListenerT
>::next()
100 return (*std::as_const(maData
))[nRemain
];
103 template <class ListenerT
> void OInterfaceIteratorHelper3
<ListenerT
>::remove()
105 rCont
.removeInterface((*std::as_const(maData
))[nRemain
]);
109 A container of interfaces. To access the elements use an iterator.
110 This implementation is thread-safe.
112 This is a copy of the code at include/comphelper/interfacecontainer2.hxx,
113 except that it is templatized on the type of the listener, which allows
114 some parts of the code to avoid doing an UNO_QUERY that can be expensive
117 @tparam ListenerT UNO event listener type
118 @see OInterfaceIteratorHelper
120 template <class ListenerT
> class OInterfaceContainerHelper3
124 Create an interface container.
126 @param rMutex the mutex to protect multi thread access.
127 The lifetime must be longer than the lifetime
130 inline OInterfaceContainerHelper3(::osl::Mutex
& rMutex_
);
133 Return the number of Elements in the container. Only useful if you have acquired
136 sal_Int32
getLength() const;
139 Return all interfaces added to this container.
141 std::vector
<css::uno::Reference
<ListenerT
>> getElements() const;
143 /** Inserts an element into the container. The position is not specified, thus it is not
144 specified in which order events are fired.
147 If you add the same interface more than once, then it will be added to the elements list
148 more than once and thus if you want to remove that interface from the list, you have to call
149 removeInterface() the same number of times.
150 In the latter case, you will also get events fired more than once (if the interface is a
154 interface to be added; it is allowed to insert
155 the same interface more than once
157 the new count of elements in the container
159 sal_Int32
addInterface(const css::uno::Reference
<ListenerT
>& rxIFace
);
160 /** Removes an element from the container. It uses interface equality to remove the interface.
163 interface to be removed
165 the new count of elements in the container
167 sal_Int32
removeInterface(const css::uno::Reference
<ListenerT
>& rxIFace
);
168 /** Return an interface by index
170 const css::uno::Reference
<ListenerT
>& getInterface(sal_Int32 nIndex
) const;
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
& mrMutex
;
223 OInterfaceContainerHelper3(const OInterfaceContainerHelper3
&) = delete;
224 OInterfaceContainerHelper3
& operator=(const OInterfaceContainerHelper3
&) = delete;
226 static o3tl::cow_wrapper
<std::vector
<css::uno::Reference
<ListenerT
>>,
227 o3tl::ThreadSafeRefCountingPolicy
>&
230 static o3tl::cow_wrapper
<std::vector
<css::uno::Reference
<ListenerT
>>,
231 o3tl::ThreadSafeRefCountingPolicy
>
237 template <typename EventT
> class NotifySingleListener
240 typedef void (SAL_CALL
ListenerT::*NotificationMethod
)(const EventT
&);
241 NotificationMethod
const m_pMethod
;
242 const EventT
& m_rEvent
;
245 NotifySingleListener(NotificationMethod method
, const EventT
& event
)
251 void operator()(const css::uno::Reference
<ListenerT
>& listener
) const
253 (listener
.get()->*m_pMethod
)(m_rEvent
);
259 inline OInterfaceContainerHelper3
<T
>::OInterfaceContainerHelper3(::osl::Mutex
& rMutex_
)
260 : maData(OInterfaceContainerHelper3
<T
>::DEFAULT())
266 template <typename FuncT
>
267 inline void OInterfaceContainerHelper3
<T
>::forEach(FuncT
const& func
)
269 osl::ClearableMutexGuard
aGuard(mrMutex
);
270 if (std::as_const(maData
)->empty())
272 OInterfaceIteratorHelper3
<T
> iter(*this);
274 while (iter
.hasMoreElements())
276 auto xListener
= iter
.next();
281 catch (css::lang::DisposedException
const& exc
)
283 if (exc
.Context
== xListener
)
289 template <class ListenerT
>
290 template <typename EventT
>
291 inline void OInterfaceContainerHelper3
<ListenerT
>::notifyEach(
292 void (SAL_CALL
ListenerT::*NotificationMethod
)(const EventT
&), const EventT
& Event
)
294 forEach
<NotifySingleListener
<EventT
>>(NotifySingleListener
<EventT
>(NotificationMethod
, Event
));
297 template <class ListenerT
> sal_Int32 OInterfaceContainerHelper3
<ListenerT
>::getLength() const
299 osl::MutexGuard
aGuard(mrMutex
);
300 return maData
->size();
303 template <class ListenerT
>
304 std::vector
<css::uno::Reference
<ListenerT
>>
305 OInterfaceContainerHelper3
<ListenerT
>::getElements() const
307 std::vector
<css::uno::Reference
<ListenerT
>> rVec
;
308 osl::MutexGuard
aGuard(mrMutex
);
313 template <class ListenerT
>
315 OInterfaceContainerHelper3
<ListenerT
>::addInterface(const css::uno::Reference
<ListenerT
>& rListener
)
317 assert(rListener
.is());
318 osl::MutexGuard
aGuard(mrMutex
);
320 maData
->push_back(rListener
);
321 return std::as_const(maData
)->size();
324 template <class ListenerT
>
325 sal_Int32 OInterfaceContainerHelper3
<ListenerT
>::removeInterface(
326 const css::uno::Reference
<ListenerT
>& rListener
)
328 assert(rListener
.is());
329 osl::MutexGuard
aGuard(mrMutex
);
331 // It is not valid to compare the pointer directly, but it's faster.
332 auto it
= std::find_if(maData
->begin(), maData
->end(),
333 [&rListener
](const css::uno::Reference
<css::uno::XInterface
>& rItem
) {
334 return rItem
.get() == rListener
.get();
337 // interface not found, use the correct compare method
338 if (it
== maData
->end())
339 it
= std::find(maData
->begin(), maData
->end(), rListener
);
341 if (it
!= maData
->end())
344 return std::as_const(maData
)->size();
347 template <class ListenerT
>
348 const css::uno::Reference
<ListenerT
>&
349 OInterfaceContainerHelper3
<ListenerT
>::getInterface(sal_Int32 nIndex
) const
351 osl::MutexGuard
aGuard(mrMutex
);
353 return (*maData
)[nIndex
];
356 template <class ListenerT
>
357 void OInterfaceContainerHelper3
<ListenerT
>::disposeAndClear(const css::lang::EventObject
& rEvt
)
359 osl::ClearableMutexGuard
aGuard(mrMutex
);
360 OInterfaceIteratorHelper3
<ListenerT
> aIt(*this);
363 while (aIt
.hasMoreElements())
367 aIt
.next()->disposing(rEvt
);
369 catch (css::uno::RuntimeException
&)
371 // be robust, if e.g. a remote bridge has disposed already.
372 // there is no way to delegate the error to the caller :o(.
377 template <class ListenerT
> void OInterfaceContainerHelper3
<ListenerT
>::clear()
379 osl::MutexGuard
aGuard(mrMutex
);
384 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */