android: Update app-specific/MIME type icons
[LibreOffice.git] / include / comphelper / interfacecontainer3.hxx
blob4b3d44bab69db31aec445ad08d8ab5adfe32a76e
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 #pragma once
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>
26 #include <vector>
28 namespace com::sun::star::uno
30 class XInterface;
32 namespace osl
34 class Mutex;
37 namespace comphelper
39 template <class ListenerT> class OInterfaceContainerHelper3;
40 /**
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
50 public:
51 /**
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_)
64 : rCont(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.
82 void remove();
84 private:
85 OInterfaceContainerHelper3<ListenerT>& rCont;
86 o3tl::cow_wrapper<std::vector<css::uno::Reference<ListenerT>>,
87 o3tl::ThreadSafeRefCountingPolicy>
88 maData;
89 sal_Int32 nRemain;
91 OInterfaceIteratorHelper3(const OInterfaceIteratorHelper3&) = delete;
92 OInterfaceIteratorHelper3& operator=(const OInterfaceIteratorHelper3&) = delete;
95 template <class ListenerT>
96 const css::uno::Reference<ListenerT>& OInterfaceIteratorHelper3<ListenerT>::next()
98 nRemain--;
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
114 in bulk.
116 @tparam ListenerT UNO event listener type
117 @see OInterfaceIteratorHelper
119 template <class ListenerT> class OInterfaceContainerHelper3
121 public:
123 Create an interface container.
125 @param rMutex the mutex to protect multi thread access.
126 The lifetime must be longer than the lifetime
127 of this object.
129 inline OInterfaceContainerHelper3(::osl::Mutex& rMutex_);
132 Return the number of Elements in the container. Only useful if you have acquired
133 the mutex.
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.
145 @attention
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
150 listener interface).
152 @param rxIFace
153 interface to be added; it is allowed to insert
154 the same interface more than once
155 @return
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.
161 @param rxIFace
162 interface to be removed
163 @return
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().
178 void clear();
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.
203 @param Event
204 Event to notify to all contained listeners
206 Example:
207 @code
208 awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
209 listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
210 @endcode
212 template <typename EventT>
213 inline void notifyEach(void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&),
214 const EventT& Event);
216 private:
217 friend class OInterfaceIteratorHelper3<ListenerT>;
218 o3tl::cow_wrapper<std::vector<css::uno::Reference<ListenerT>>,
219 o3tl::ThreadSafeRefCountingPolicy>
220 maData;
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>&
227 DEFAULT()
229 static o3tl::cow_wrapper<std::vector<css::uno::Reference<ListenerT>>,
230 o3tl::ThreadSafeRefCountingPolicy>
231 SINGLETON;
232 return SINGLETON;
235 private:
236 template <typename EventT> class NotifySingleListener
238 private:
239 typedef void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&);
240 NotificationMethod const m_pMethod;
241 const EventT& m_rEvent;
243 public:
244 NotifySingleListener(NotificationMethod method, const EventT& event)
245 : m_pMethod(method)
246 , m_rEvent(event)
250 void operator()(const css::uno::Reference<ListenerT>& listener) const
252 (listener.get()->*m_pMethod)(m_rEvent);
257 template <class T>
258 inline OInterfaceContainerHelper3<T>::OInterfaceContainerHelper3(::osl::Mutex& rMutex_)
259 : maData(OInterfaceContainerHelper3<T>::DEFAULT())
260 , mrMutex(rMutex_)
264 template <class T>
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();
274 func(xListener);
276 catch (css::lang::DisposedException const& exc)
278 if (exc.Context == xListener)
279 iter.remove();
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);
304 rVec = *maData;
305 return rVec;
308 template <class ListenerT>
309 sal_Int32
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())
337 maData->erase(it);
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);
356 maData->clear();
357 aGuard.clear();
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);
375 maData->clear();
379 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */