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 , nRemain(maData
->size())
70 /** Return true, if there are more elements in the iterator. */
71 bool hasMoreElements() const { return nRemain
!= 0; }
72 /** Return the next element of the iterator. Calling this method if
73 hasMoreElements() has returned false, is an error.
75 css::uno::Reference
<ListenerT
> const& next();
77 /** Removes the current element (the last one returned by next())
78 from the underlying container. Calling this method before
79 next() has been called or calling it twice with no next()
80 in between is an error.
85 OInterfaceContainerHelper3
<ListenerT
>& rCont
;
86 o3tl::cow_wrapper
<std::vector
<css::uno::Reference
<ListenerT
>>,
87 o3tl::ThreadSafeRefCountingPolicy
>
91 OInterfaceIteratorHelper3(const OInterfaceIteratorHelper3
&) = delete;
92 OInterfaceIteratorHelper3
& operator=(const OInterfaceIteratorHelper3
&) = delete;
95 template <class ListenerT
>
96 const css::uno::Reference
<ListenerT
>& OInterfaceIteratorHelper3
<ListenerT
>::next()
99 return (*maData
)[nRemain
];
102 template <class ListenerT
> void OInterfaceIteratorHelper3
<ListenerT
>::remove()
104 rCont
.removeInterface((*maData
)[nRemain
]);
108 A container of interfaces. To access the elements use an iterator.
109 This implementation is thread-safe.
111 This is a copy of the code at include/comphelper/interfacecontainer2.hxx,
112 except that it is templatized on the type of the listener, which allows
113 some parts of the code to avoid doing an UNO_QUERY that can be expensive
116 @tparam ListenerT UNO event listener type
117 @see OInterfaceIteratorHelper
119 template <class ListenerT
> class OInterfaceContainerHelper3
123 Create an interface container.
125 @param rMutex the mutex to protect multi thread access.
126 The lifetime must be longer than the lifetime
129 inline OInterfaceContainerHelper3(::osl::Mutex
& rMutex_
);
132 Return the number of Elements in the container. Only useful if you have acquired
135 sal_Int32
getLength() const;
138 Return all interfaces added to this container.
140 std::vector
<css::uno::Reference
<ListenerT
>> getElements() const;
142 /** Inserts an element into the container. The position is not specified, thus it is not
143 specified in which order events are fired.
146 If you add the same interface more than once, then it will be added to the elements list
147 more than once and thus if you want to remove that interface from the list, you have to call
148 removeInterface() the same number of times.
149 In the latter case, you will also get events fired more than once (if the interface is a
153 interface to be added; it is allowed to insert
154 the same interface more than once
156 the new count of elements in the container
158 sal_Int32
addInterface(const css::uno::Reference
<ListenerT
>& rxIFace
);
159 /** Removes an element from the container. It uses interface equality to remove the interface.
162 interface to be removed
164 the new count of elements in the container
166 sal_Int32
removeInterface(const css::uno::Reference
<ListenerT
>& rxIFace
);
167 /** Return an interface by index
169 const css::uno::Reference
<ListenerT
>& getInterface(sal_Int32 nIndex
) const;
171 Call disposing on all object in the container that
172 support XEventListener. Then clear the container.
174 void disposeAndClear(const css::lang::EventObject
& rEvt
);
176 Clears the container without calling disposing().
180 /** Executes a functor for each contained listener of specified type, e.g.
181 <code>forEach<awt::XPaintListener>(...</code>.
183 If a css::lang::DisposedException occurs which relates to
184 the called listener, then that listener is removed from the container.
186 @tparam FuncT unary functor type, let your compiler deduce this for you
187 @param func unary functor object expecting an argument of type
188 css::uno::Reference<ListenerT>
190 template <typename FuncT
> inline void forEach(FuncT
const& func
);
192 /** Calls a UNO listener method for each contained listener.
194 The listener method must take a single argument of type EventT,
195 and return <code>void</code>.
197 If a css::lang::DisposedException occurs which relates to
198 the called listener, then that listener is removed from the container.
200 @tparam EventT event type, let your compiler deduce this for you
201 @param NotificationMethod
202 Pointer to a method of a ListenerT interface.
204 Event to notify to all contained listeners
208 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
209 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
212 template <typename EventT
>
213 inline void notifyEach(void (SAL_CALL
ListenerT::*NotificationMethod
)(const EventT
&),
214 const EventT
& Event
);
217 friend class OInterfaceIteratorHelper3
<ListenerT
>;
218 o3tl::cow_wrapper
<std::vector
<css::uno::Reference
<ListenerT
>>,
219 o3tl::ThreadSafeRefCountingPolicy
>
221 ::osl::Mutex
& mrMutex
;
222 OInterfaceContainerHelper3(const OInterfaceContainerHelper3
&) = delete;
223 OInterfaceContainerHelper3
& operator=(const OInterfaceContainerHelper3
&) = delete;
225 static o3tl::cow_wrapper
<std::vector
<css::uno::Reference
<ListenerT
>>,
226 o3tl::ThreadSafeRefCountingPolicy
>&
229 static o3tl::cow_wrapper
<std::vector
<css::uno::Reference
<ListenerT
>>,
230 o3tl::ThreadSafeRefCountingPolicy
>
236 template <typename EventT
> class NotifySingleListener
239 typedef void (SAL_CALL
ListenerT::*NotificationMethod
)(const EventT
&);
240 NotificationMethod
const m_pMethod
;
241 const EventT
& m_rEvent
;
244 NotifySingleListener(NotificationMethod method
, const EventT
& event
)
250 void operator()(const css::uno::Reference
<ListenerT
>& listener
) const
252 (listener
.get()->*m_pMethod
)(m_rEvent
);
258 inline OInterfaceContainerHelper3
<T
>::OInterfaceContainerHelper3(::osl::Mutex
& rMutex_
)
259 : maData(OInterfaceContainerHelper3
<T
>::DEFAULT())
265 template <typename FuncT
>
266 inline void OInterfaceContainerHelper3
<T
>::forEach(FuncT
const& func
)
268 OInterfaceIteratorHelper3
<T
> iter(*this);
269 while (iter
.hasMoreElements())
271 auto xListener
= iter
.next();
276 catch (css::lang::DisposedException
const& exc
)
278 if (exc
.Context
== xListener
)
284 template <class ListenerT
>
285 template <typename EventT
>
286 inline void OInterfaceContainerHelper3
<ListenerT
>::notifyEach(
287 void (SAL_CALL
ListenerT::*NotificationMethod
)(const EventT
&), const EventT
& Event
)
289 forEach
<NotifySingleListener
<EventT
>>(NotifySingleListener
<EventT
>(NotificationMethod
, Event
));
292 template <class ListenerT
> sal_Int32 OInterfaceContainerHelper3
<ListenerT
>::getLength() const
294 osl::MutexGuard
aGuard(mrMutex
);
295 return maData
->size();
298 template <class ListenerT
>
299 std::vector
<css::uno::Reference
<ListenerT
>>
300 OInterfaceContainerHelper3
<ListenerT
>::getElements() const
302 std::vector
<css::uno::Reference
<ListenerT
>> rVec
;
303 osl::MutexGuard
aGuard(mrMutex
);
308 template <class ListenerT
>
310 OInterfaceContainerHelper3
<ListenerT
>::addInterface(const css::uno::Reference
<ListenerT
>& rListener
)
312 assert(rListener
.is());
313 osl::MutexGuard
aGuard(mrMutex
);
315 maData
->push_back(rListener
);
316 return maData
->size();
319 template <class ListenerT
>
320 sal_Int32 OInterfaceContainerHelper3
<ListenerT
>::removeInterface(
321 const css::uno::Reference
<ListenerT
>& rListener
)
323 assert(rListener
.is());
324 osl::MutexGuard
aGuard(mrMutex
);
326 // It is not valid to compare the pointer directly, but it's faster.
327 auto it
= std::find_if(maData
->begin(), maData
->end(),
328 [&rListener
](const css::uno::Reference
<css::uno::XInterface
>& rItem
) {
329 return rItem
.get() == rListener
.get();
332 // interface not found, use the correct compare method
333 if (it
== maData
->end())
334 it
= std::find(maData
->begin(), maData
->end(), rListener
);
336 if (it
!= maData
->end())
339 return maData
->size();
342 template <class ListenerT
>
343 const css::uno::Reference
<ListenerT
>&
344 OInterfaceContainerHelper3
<ListenerT
>::getInterface(sal_Int32 nIndex
) const
346 osl::MutexGuard
aGuard(mrMutex
);
348 return (*maData
)[nIndex
];
351 template <class ListenerT
>
352 void OInterfaceContainerHelper3
<ListenerT
>::disposeAndClear(const css::lang::EventObject
& rEvt
)
354 osl::ClearableMutexGuard
aGuard(mrMutex
);
355 OInterfaceIteratorHelper3
<ListenerT
> aIt(*this);
358 while (aIt
.hasMoreElements())
362 aIt
.next()->disposing(rEvt
);
364 catch (css::uno::RuntimeException
&)
366 // be robust, if e.g. a remote bridge has disposed already.
367 // there is no way to delegate the error to the caller :o(.
372 template <class ListenerT
> void OInterfaceContainerHelper3
<ListenerT
>::clear()
374 osl::MutexGuard
aGuard(mrMutex
);
379 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */