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>
27 #include <o3tl/cow_wrapper.hxx>
28 #include <vector>
29 
30 namespace com
31 {
32 namespace sun
33 {
34 namespace star
35 {
36 namespace uno
37 {
38 class XInterface;
39 }
40 }
41 }
42 }
43 namespace osl
44 {
45 class Mutex;
46 }
47  //for docpp
49 namespace comphelper
50 {
51 template <class ListenerT> class OInterfaceContainerHelper3;
60 template <class ListenerT> class OInterfaceIteratorHelper3
61 {
62 public:
76  : rCont(rCont_)
78  , nRemain(maData->size())
79  {
80  }
81 
83  bool hasMoreElements() const { return nRemain != 0; }
87  css::uno::Reference<ListenerT> const& next();
88 
94  void remove();
95 
96 private:
99  sal_Int32 nRemain;
100 
103 };
104 
105 template <class ListenerT>
106 const css::uno::Reference<ListenerT>& OInterfaceIteratorHelper3<ListenerT>::next()
107 {
108  nRemain--;
109  return (*maData)[nRemain];
110 }
111 
112 template <class ListenerT> void OInterfaceIteratorHelper3<ListenerT>::remove()
113 {
114  rCont.removeInterface((*maData)[nRemain]);
115 }
116 
124 template <class ListenerT> class OInterfaceContainerHelper3
125 {
126 public:
134  OInterfaceContainerHelper3(::osl::Mutex& rMutex_)
135  : rMutex(rMutex_)
136  {
137  }
142  sal_Int32 getLength() const;
143 
147  std::vector<css::uno::Reference<ListenerT>> getElements() const;
148 
165  sal_Int32 addInterface(const css::uno::Reference<ListenerT>& rxIFace);
173  sal_Int32 removeInterface(const css::uno::Reference<ListenerT>& rxIFace);
178  void disposeAndClear(const css::lang::EventObject& rEvt);
182  void clear();
183 
194  template <typename FuncT> inline void forEach(FuncT const& func);
195 
216  template <typename EventT>
217  inline void notifyEach(void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&),
218  const EventT& Event);
219 
220 private:
221  friend class OInterfaceIteratorHelper3<ListenerT>;
223  ::osl::Mutex& rMutex;
226 
227 private:
228  template <typename EventT> class NotifySingleListener
229  {
230  private:
231  typedef void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&);
232  NotificationMethod const m_pMethod;
233  const EventT& m_rEvent;
234 
235  public:
236  NotifySingleListener(NotificationMethod method, const EventT& event)
237  : m_pMethod(method)
238  , m_rEvent(event)
239  {
240  }
241 
242  void operator()(const css::uno::Reference<ListenerT>& listener) const
243  {
244  (listener.get()->*m_pMethod)(m_rEvent);
245  }
246  };
247 };
248 
249 template <class T>
250 template <typename FuncT>
251 inline void OInterfaceContainerHelper3<T>::forEach(FuncT const& func)
252 {
253  OInterfaceIteratorHelper3<T> iter(*this);
254  while (iter.hasMoreElements())
255  {
256  auto xListener = iter.next();
257  try
258  {
259  func(xListener);
260  }
261  catch (css::lang::DisposedException const& exc)
262  {
263  if (exc.Context == xListener)
264  iter.remove();
265  }
266  }
267 }
268 
269 template <class ListenerT>
270 template <typename EventT>
272  void (SAL_CALL ListenerT::*NotificationMethod)(const EventT&), const EventT& Event)
273 {
274  forEach<NotifySingleListener<EventT>>(NotifySingleListener<EventT>(NotificationMethod, Event));
275 }
276 
277 template <class ListenerT> sal_Int32 OInterfaceContainerHelper3<ListenerT>::getLength() const
278 {
279  osl::MutexGuard aGuard(rMutex);
280  return maData->size();
281 }
282 
283 template <class ListenerT>
284 std::vector<css::uno::Reference<ListenerT>>
286 {
287  std::vector<css::uno::Reference<ListenerT>> rVec;
288  osl::MutexGuard aGuard(rMutex);
289  rVec = *maData;
290  return rVec;
291 }
292 
293 template <class ListenerT>
294 sal_Int32
295 OInterfaceContainerHelper3<ListenerT>::addInterface(const css::uno::Reference<ListenerT>& rListener)
296 {
297  assert(rListener.is());
298  osl::MutexGuard aGuard(rMutex);
299 
300  maData->push_back(rListener);
301  return maData->size();
302 }
303 
304 template <class ListenerT>
306  const css::uno::Reference<ListenerT>& rListener)
307 {
308  assert(rListener.is());
309  osl::MutexGuard aGuard(rMutex);
310 
311  // It is not valid to compare the pointer directly, but it's faster.
312  auto it = std::find_if(maData->begin(), maData->end(),
313  [&rListener](const css::uno::Reference<css::uno::XInterface>& rItem) {
314  return rItem.get() == rListener.get();
315  });
316 
317  // interface not found, use the correct compare method
318  if (it == maData->end())
319  it = std::find(maData->begin(), maData->end(), rListener);
320 
321  if (it != maData->end())
322  maData->erase(it);
323 
324  return maData->size();
325 }
326 
327 template <class ListenerT>
328 void OInterfaceContainerHelper3<ListenerT>::disposeAndClear(const css::lang::EventObject& rEvt)
329 {
330  osl::ClearableMutexGuard aGuard(rMutex);
332  maData->clear();
333  aGuard.clear();
334  while (aIt.hasMoreElements())
335  {
336  try
337  {
338  aIt.next()->disposing(rEvt);
339  }
340  catch (css::uno::RuntimeException&)
341  {
342  // be robust, if e.g. a remote bridge has disposed already.
343  // there is no way to delegate the error to the caller :o(.
344  }
345  }
346 }
347 
348 template <class ListenerT> void OInterfaceContainerHelper3<ListenerT>::clear()
349 {
350  osl::MutexGuard aGuard(rMutex);
351  maData->clear();
352 }
353 }
354 #endif
355 
356 /* 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
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
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
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.