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 
119 template <class ListenerT> class OInterfaceContainerHelper3
120 {
121 public:
129  OInterfaceContainerHelper3(::osl::Mutex& rMutex_)
130  : rMutex(rMutex_)
131  {
132  }
137  sal_Int32 getLength() const;
138 
142  std::vector<css::uno::Reference<ListenerT>> getElements() const;
143 
160  sal_Int32 addInterface(const css::uno::Reference<ListenerT>& rxIFace);
168  sal_Int32 removeInterface(const css::uno::Reference<ListenerT>& rxIFace);
173  void disposeAndClear(const css::lang::EventObject& rEvt);
177  void clear();
178 
189  template <typename FuncT> inline void forEach(FuncT const& func);
190 
211  template <typename EventT>
212  inline void notifyEach(void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&),
213  const EventT& Event);
214 
215 private:
216  friend class OInterfaceIteratorHelper3<ListenerT>;
218  ::osl::Mutex& rMutex;
221 
222 private:
223  template <typename EventT> class NotifySingleListener
224  {
225  private:
226  typedef void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&);
227  NotificationMethod const m_pMethod;
228  const EventT& m_rEvent;
229 
230  public:
231  NotifySingleListener(NotificationMethod method, const EventT& event)
232  : m_pMethod(method)
233  , m_rEvent(event)
234  {
235  }
236 
237  void operator()(const css::uno::Reference<ListenerT>& listener) const
238  {
239  (listener.get()->*m_pMethod)(m_rEvent);
240  }
241  };
242 };
243 
244 template <class T>
245 template <typename FuncT>
246 inline void OInterfaceContainerHelper3<T>::forEach(FuncT const& func)
247 {
248  OInterfaceIteratorHelper3<T> iter(*this);
249  while (iter.hasMoreElements())
250  {
251  auto xListener = iter.next();
252  try
253  {
254  func(xListener);
255  }
256  catch (css::lang::DisposedException const& exc)
257  {
258  if (exc.Context == xListener)
259  iter.remove();
260  }
261  }
262 }
263 
264 template <class ListenerT>
265 template <typename EventT>
267  void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&), const EventT& Event)
268 {
269  forEach<NotifySingleListener<EventT>>(NotifySingleListener<EventT>(NotificationMethod, Event));
270 }
271 
272 template <class ListenerT> sal_Int32 OInterfaceContainerHelper3<ListenerT>::getLength() const
273 {
274  osl::MutexGuard aGuard(rMutex);
275  return maData->size();
276 }
277 
278 template <class ListenerT>
279 std::vector<css::uno::Reference<ListenerT>>
281 {
282  std::vector<css::uno::Reference<ListenerT>> rVec;
283  osl::MutexGuard aGuard(rMutex);
284  rVec = *maData;
285  return rVec;
286 }
287 
288 template <class ListenerT>
289 sal_Int32
290 OInterfaceContainerHelper3<ListenerT>::addInterface(const css::uno::Reference<ListenerT>& rListener)
291 {
292  assert(rListener.is());
293  osl::MutexGuard aGuard(rMutex);
294 
295  maData->push_back(rListener);
296  return maData->size();
297 }
298 
299 template <class ListenerT>
301  const css::uno::Reference<ListenerT>& rListener)
302 {
303  assert(rListener.is());
304  osl::MutexGuard aGuard(rMutex);
305 
306  // It is not valid to compare the pointer directly, but it's faster.
307  auto it = std::find_if(maData->begin(), maData->end(),
308  [&rListener](const css::uno::Reference<css::uno::XInterface>& rItem) {
309  return rItem.get() == rListener.get();
310  });
311 
312  // interface not found, use the correct compare method
313  if (it == maData->end())
314  it = std::find(maData->begin(), maData->end(), rListener);
315 
316  if (it != maData->end())
317  maData->erase(it);
318 
319  return maData->size();
320 }
321 
322 template <class ListenerT>
323 void OInterfaceContainerHelper3<ListenerT>::disposeAndClear(const css::lang::EventObject& rEvt)
324 {
325  osl::ClearableMutexGuard aGuard(rMutex);
327  maData->clear();
328  aGuard.clear();
329  while (aIt.hasMoreElements())
330  {
331  try
332  {
333  aIt.next()->disposing(rEvt);
334  }
335  catch (css::uno::RuntimeException&)
336  {
337  // be robust, if e.g. a remote bridge has disposed already.
338  // there is no way to delegate the error to the caller :o(.
339  }
340  }
341 }
342 
343 template <class ListenerT> void OInterfaceContainerHelper3<ListenerT>::clear()
344 {
345  osl::MutexGuard aGuard(rMutex);
346  maData->clear();
347 }
348 }
349 #endif
350 
351 /* 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 OInterfaceContainerHelper3.
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
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
static PropertyMapEntry const * find(const rtl::Reference< PropertySetInfo > &mxInfo, const OUString &aName) noexcept
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.