LibreOffice Module comphelper (master)  1
interfacecontainer3.hxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 #ifndef INCLUDED_COMPHELPER_INTERFACECONTAINER3_H
20 #define INCLUDED_COMPHELPER_INTERFACECONTAINER3_H
21 
22 #include <sal/config.h>
23 
24 #include <com/sun/star/lang/EventObject.hpp>
25 #include <com/sun/star/lang/DisposedException.hpp>
26 #include <o3tl/cow_wrapper.hxx>
27 #include <vector>
28 
29 namespace com::sun::star::uno
30 {
31 class XInterface;
32 }
33 namespace osl
34 {
35 class Mutex;
36 }
37  //for docpp
39 namespace comphelper
40 {
41 template <class ListenerT> class OInterfaceContainerHelper3;
50 template <class ListenerT> class OInterfaceIteratorHelper3
51 {
52 public:
66  : rCont(rCont_)
68  , nRemain(maData->size())
69  {
70  }
71 
73  bool hasMoreElements() const { return nRemain != 0; }
77  css::uno::Reference<ListenerT> const& next();
78 
84  void remove();
85 
86 private:
89  sal_Int32 nRemain;
90 
93 };
94 
95 template <class ListenerT>
96 const css::uno::Reference<ListenerT>& OInterfaceIteratorHelper3<ListenerT>::next()
97 {
98  nRemain--;
99  return (*maData)[nRemain];
100 }
101 
102 template <class ListenerT> void OInterfaceIteratorHelper3<ListenerT>::remove()
103 {
104  rCont.removeInterface((*maData)[nRemain]);
105 }
106 
114 template <class ListenerT> class OInterfaceContainerHelper3
115 {
116 public:
124  OInterfaceContainerHelper3(::osl::Mutex& rMutex_)
125  : rMutex(rMutex_)
126  {
127  }
132  sal_Int32 getLength() const;
133 
137  std::vector<css::uno::Reference<ListenerT>> getElements() const;
138 
155  sal_Int32 addInterface(const css::uno::Reference<ListenerT>& rxIFace);
163  sal_Int32 removeInterface(const css::uno::Reference<ListenerT>& rxIFace);
168  void disposeAndClear(const css::lang::EventObject& rEvt);
172  void clear();
173 
184  template <typename FuncT> inline void forEach(FuncT const& func);
185 
206  template <typename EventT>
207  inline void notifyEach(void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&),
208  const EventT& Event);
209 
210 private:
211  friend class OInterfaceIteratorHelper3<ListenerT>;
213  ::osl::Mutex& rMutex;
216 
217 private:
218  template <typename EventT> class NotifySingleListener
219  {
220  private:
221  typedef void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&);
222  NotificationMethod const m_pMethod;
223  const EventT& m_rEvent;
224 
225  public:
226  NotifySingleListener(NotificationMethod method, const EventT& event)
227  : m_pMethod(method)
228  , m_rEvent(event)
229  {
230  }
231 
232  void operator()(const css::uno::Reference<ListenerT>& listener) const
233  {
234  (listener.get()->*m_pMethod)(m_rEvent);
235  }
236  };
237 };
238 
239 template <class T>
240 template <typename FuncT>
241 inline void OInterfaceContainerHelper3<T>::forEach(FuncT const& func)
242 {
243  OInterfaceIteratorHelper3<T> iter(*this);
244  while (iter.hasMoreElements())
245  {
246  auto xListener = iter.next();
247  try
248  {
249  func(xListener);
250  }
251  catch (css::lang::DisposedException const& exc)
252  {
253  if (exc.Context == xListener)
254  iter.remove();
255  }
256  }
257 }
258 
259 template <class ListenerT>
260 template <typename EventT>
262  void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&), const EventT& Event)
263 {
264  forEach<NotifySingleListener<EventT>>(NotifySingleListener<EventT>(NotificationMethod, Event));
265 }
266 
267 template <class ListenerT> sal_Int32 OInterfaceContainerHelper3<ListenerT>::getLength() const
268 {
269  osl::MutexGuard aGuard(rMutex);
270  return maData->size();
271 }
272 
273 template <class ListenerT>
274 std::vector<css::uno::Reference<ListenerT>>
276 {
277  std::vector<css::uno::Reference<ListenerT>> rVec;
278  osl::MutexGuard aGuard(rMutex);
279  rVec = *maData;
280  return rVec;
281 }
282 
283 template <class ListenerT>
284 sal_Int32
285 OInterfaceContainerHelper3<ListenerT>::addInterface(const css::uno::Reference<ListenerT>& rListener)
286 {
287  assert(rListener.is());
288  osl::MutexGuard aGuard(rMutex);
289 
290  maData->push_back(rListener);
291  return maData->size();
292 }
293 
294 template <class ListenerT>
296  const css::uno::Reference<ListenerT>& rListener)
297 {
298  assert(rListener.is());
299  osl::MutexGuard aGuard(rMutex);
300 
301  // It is not valid to compare the pointer directly, but it's faster.
302  auto it = std::find_if(maData->begin(), maData->end(),
303  [&rListener](const css::uno::Reference<css::uno::XInterface>& rItem) {
304  return rItem.get() == rListener.get();
305  });
306 
307  // interface not found, use the correct compare method
308  if (it == maData->end())
309  it = std::find(maData->begin(), maData->end(), rListener);
310 
311  if (it != maData->end())
312  maData->erase(it);
313 
314  return maData->size();
315 }
316 
317 template <class ListenerT>
318 void OInterfaceContainerHelper3<ListenerT>::disposeAndClear(const css::lang::EventObject& rEvt)
319 {
320  osl::ClearableMutexGuard aGuard(rMutex);
322  maData->clear();
323  aGuard.clear();
324  while (aIt.hasMoreElements())
325  {
326  try
327  {
328  aIt.next()->disposing(rEvt);
329  }
330  catch (css::uno::RuntimeException&)
331  {
332  // be robust, if e.g. a remote bridge has disposed already.
333  // there is no way to delegate the error to the caller :o(.
334  }
335  }
336 }
337 
338 template <class ListenerT> void OInterfaceContainerHelper3<ListenerT>::clear()
339 {
340  osl::MutexGuard aGuard(rMutex);
341  maData->clear();
342 }
343 }
344 #endif
345 
346 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OInterfaceContainerHelper3(::osl::Mutex &rMutex_)
Create an interface container.
bool hasMoreElements() const
Return true, if there are more elements in the iterator.
void clear()
Clears the container without calling disposing().
OInterfaceIteratorHelper3 & operator=(const OInterfaceIteratorHelper3 &)=delete
sal_Int32 addInterface(const css::uno::Reference< ListenerT > &rxIFace)
Inserts an element into the container.
std::vector< css::uno::Reference< ListenerT > > getElements() const
Return all interfaces added to this container.
OInterfaceContainerHelper3 & operator=(const OInterfaceContainerHelper3 &)=delete
std::vector< sal_Int8 > maData
This is the iterator of an InterfaceContainerHelper.
o3tl::cow_wrapper< std::vector< css::uno::Reference< ListenerT > > > maData
sal_Int32 getLength() const
Return the number of Elements in the container.
void forEach(FuncT const &func)
Executes a functor for each contained listener of specified type, e.g.
void remove()
Removes the current element (the last one returned by next()) from the underlying container...
sal_Int32 removeInterface(const css::uno::Reference< ListenerT > &rxIFace)
Removes an element from the container.
css::uno::Reference< ListenerT > const & next()
Return the next element of the iterator.
typedef void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &)
size
static PropertyMapEntry const * find(rtl::Reference< PropertySetInfo > &mxInfo, const OUString &aName) noexcept
void notifyEach(void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
Calls a UNO listener method for each contained listener.
OInterfaceIteratorHelper3(OInterfaceContainerHelper3< ListenerT > &rCont_)
Create an iterator over the elements of the container.
void operator()(const css::uno::Reference< ListenerT > &listener) const
o3tl::cow_wrapper< std::vector< css::uno::Reference< ListenerT > > > maData
NotifySingleListener(NotificationMethod method, const EventT &event)
OInterfaceContainerHelper3< ListenerT > & rCont
void disposeAndClear(const css::lang::EventObject &rEvt)
Call disposing on all object in the container that support XEventListener.