Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/comphelper/interfacecontainer2.hxx
Line
Count
Source
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_INTERFACECONTAINER2_H
20
#define INCLUDED_COMPHELPER_INTERFACECONTAINER2_H
21
22
#include <sal/config.h>
23
24
#include <vector>
25
26
#include <com/sun/star/lang/DisposedException.hpp>
27
#include <comphelper/comphelperdllapi.h>
28
29
namespace com::sun::star::lang { struct EventObject; }
30
namespace com::sun::star::uno { class XInterface; }
31
namespace osl { class Mutex; }
32
33
namespace comphelper
34
{
35
36
namespace detail {
37
38
    /**
39
      This is here to optimise space in the common case that there are zero or one
40
      listeners.
41
    */
42
    union element_alias2
43
    {
44
        std::vector< css::uno::Reference< css::uno::XInterface > > *pAsVector;
45
        css::uno::XInterface * pAsInterface;
46
288k
        element_alias2() : pAsInterface(nullptr) {}
47
    };
48
49
}
50
51
52
class OInterfaceContainerHelper2;
53
/**
54
  This is the iterator of an OInterfaceContainerHelper2. Typically
55
  one constructs an instance on the stack for one firing session.
56
  It is not allowed to assign or copy an instance of this class.
57
58
  @see OInterfaceContainerHelper2
59
 */
60
class COMPHELPER_DLLPUBLIC OInterfaceIteratorHelper2
61
{
62
public:
63
    /**
64
       Create an iterator over the elements of the container. The iterator
65
       copies the elements of the container. A change to the container
66
       during the lifetime of an iterator is allowed and does not
67
       affect the iterator-instance. The iterator and the container take cares
68
       themself for concurrent access, no additional guarding is necessary.
69
70
       Remark: The copy is on demand. The iterator copy the elements only if the container
71
       change the contents. It is not allowed to destroy the container as long
72
       as an iterator exist.
73
74
       @param rCont the container of the elements.
75
     */
76
    OInterfaceIteratorHelper2( OInterfaceContainerHelper2 & rCont );
77
78
    /**
79
      Releases the connection to the container.
80
     */
81
    ~OInterfaceIteratorHelper2();
82
83
    /** Return true, if there are more elements in the iterator. */
84
    bool hasMoreElements() const
85
361k
        { return nRemain != 0; }
86
    /** Return the next element of the iterator. Calling this method if
87
        hasMoreElements() has returned false, is an error. Cast the
88
        returned pointer to the
89
     */
90
    css::uno::XInterface * next();
91
92
    /** Removes the current element (the last one returned by next())
93
        from the underlying container. Calling this method before
94
        next() has been called or calling it twice with no next()
95
        inbetween is an error.
96
    */
97
    void remove();
98
99
private:
100
    OInterfaceContainerHelper2 & rCont;
101
    detail::element_alias2       aData;
102
    sal_Int32                    nRemain;
103
    bool                         bIsList;
104
105
    OInterfaceIteratorHelper2( const OInterfaceIteratorHelper2 & ) = delete;
106
    OInterfaceIteratorHelper2 &  operator = ( const OInterfaceIteratorHelper2 & ) = delete;
107
};
108
109
110
/**
111
  A container of interfaces. To access the elements use an iterator.
112
  This implementation is thread-safe.
113
114
  This is a copy of the code at include/cppuhelper/interfacecontainer.h,
115
  Except that it uses a std::vector instead of a Sequence for the mutable listener
116
  list, which provides far better performance.
117
118
  @see OInterfaceIteratorHelper2
119
 */
120
class COMPHELPER_DLLPUBLIC OInterfaceContainerHelper2
121
{
122
public:
123
    /**
124
       Create an interface container.
125
126
       @param rMutex    the mutex to protect multi thread access.
127
       The lifetime must be longer than the lifetime
128
       of this object.
129
     */
130
    OInterfaceContainerHelper2( ::osl::Mutex & rMutex );
131
    /**
132
      Release all interfaces. All iterators must be destroyed before
133
      the container is destructed.
134
     */
135
    ~OInterfaceContainerHelper2();
136
    /**
137
      Return the number of Elements in the container. Only useful if you have acquired
138
      the mutex.
139
     */
140
    sal_Int32 getLength() const;
141
142
    /**
143
      Return all interfaces added to this container.
144
     **/
145
    std::vector< css::uno::Reference< css::uno::XInterface > > getElements() const;
146
147
    /** Inserts an element into the container.  The position is not specified, thus it is not
148
        specified in which order events are fired.
149
150
        @attention
151
        If you add the same interface more than once, then it will be added to the elements list
152
        more than once and thus if you want to remove that interface from the list, you have to call
153
        removeInterface() the same number of times.
154
        In the latter case, you will also get events fired more than once (if the interface is a
155
        listener interface).
156
157
        @param rxIFace
158
               interface to be added; it is allowed to insert null or
159
               the same interface more than once
160
        @return
161
                the new count of elements in the container
162
    */
163
    sal_Int32 addInterface( const css::uno::Reference< css::uno::XInterface > & rxIFace );
164
    /** Removes an element from the container.  It uses interface equality to remove the interface.
165
166
        @param rxIFace
167
               interface to be removed
168
        @return
169
                the new count of elements in the container
170
    */
171
    sal_Int32 removeInterface( const css::uno::Reference< css::uno::XInterface > & rxIFace );
172
    /** Return an interface by index */
173
    css::uno::Reference< css::uno::XInterface > getInterface(sal_Int32 nIndex) const;
174
    /**
175
      Call disposing on all object in the container that
176
      support XEventListener. Then clear the container.
177
     */
178
    void disposeAndClear( const css::lang::EventObject & rEvt );
179
    /**
180
      Clears the container without calling disposing().
181
     */
182
    void clear();
183
184
    /** Executes a functor for each contained listener of specified type, e.g.
185
        <code>forEach<awt::XPaintListener>(...</code>.
186
187
        If a css::lang::DisposedException occurs which relates to
188
        the called listener, then that listener is removed from the container.
189
190
        @tparam ListenerT listener type
191
        @tparam FuncT unary functor type, let your compiler deduce this for you
192
        @param func unary functor object expecting an argument of type
193
                    css::uno::Reference<ListenerT>
194
    */
195
    template <typename ListenerT, typename FuncT>
196
    inline void forEach( FuncT const& func );
197
198
    /** Calls a UNO listener method for each contained listener.
199
200
        The listener method must take a single argument of type EventT,
201
        and return <code>void</code>.
202
203
        If a css::lang::DisposedException occurs which relates to
204
        the called listener, then that listener is removed from the container.
205
206
        @tparam ListenerT UNO event listener type, let your compiler deduce this for you
207
        @tparam EventT event type, let your compiler deduce this for you
208
        @param NotificationMethod
209
            Pointer to a method of a ListenerT interface.
210
        @param Event
211
            Event to notify to all contained listeners
212
213
        Example:
214
@code
215
    awt::PaintEvent aEvent( static_cast< cppu::OWeakObject* >( this ), ... );
216
    listeners.notifyEach( &XPaintListener::windowPaint, aEvent );
217
@endcode
218
    */
219
    template< typename ListenerT, typename EventT >
220
    inline void notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event );
221
222
private:
223
friend class OInterfaceIteratorHelper2;
224
    /**
225
      bIsList == TRUE -> aData.pAsVector of type vector< XInterfaceSequence >,
226
      otherwise aData.pAsInterface == of type (XEventListener *)
227
     */
228
    detail::element_alias2  aData;
229
    ::osl::Mutex &          rMutex;
230
    /** TRUE -> used by an iterator. */
231
    bool                    bInUse;
232
    /** TRUE -> aData.pAsVector is of type Sequence< XInterfaceSequence >. */
233
    bool                    bIsList;
234
235
    OInterfaceContainerHelper2( const OInterfaceContainerHelper2 & ) = delete;
236
    OInterfaceContainerHelper2 & operator = ( const OInterfaceContainerHelper2 & ) = delete;
237
238
    /*
239
      Duplicate content of the container and release the old one without destroying.
240
      The mutex must be locked and the memberbInUse must be true.
241
     */
242
    void copyAndResetInUse();
243
244
private:
245
    template< typename ListenerT, typename EventT >
246
    class NotifySingleListener
247
    {
248
    private:
249
        typedef void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& );
250
        NotificationMethod const m_pMethod;
251
        const EventT&            m_rEvent;
252
    public:
253
0
        NotifySingleListener( NotificationMethod method, const EventT& event ) : m_pMethod( method ), m_rEvent( event ) { }
Unexecuted instantiation: comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::container::XContainerListener, com::sun::star::container::ContainerEvent>::NotifySingleListener(void (com::sun::star::container::XContainerListener::*)(com::sun::star::container::ContainerEvent const&), com::sun::star::container::ContainerEvent const&)
Unexecuted instantiation: comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::linguistic2::XLinguServiceEventListener, com::sun::star::linguistic2::LinguServiceEvent>::NotifySingleListener(void (com::sun::star::linguistic2::XLinguServiceEventListener::*)(com::sun::star::linguistic2::LinguServiceEvent const&), com::sun::star::linguistic2::LinguServiceEvent const&)
Unexecuted instantiation: comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::linguistic2::XDictionaryListEventListener, com::sun::star::linguistic2::DictionaryListEvent>::NotifySingleListener(void (com::sun::star::linguistic2::XDictionaryListEventListener::*)(com::sun::star::linguistic2::DictionaryListEvent const&), com::sun::star::linguistic2::DictionaryListEvent const&)
254
255
        void operator()( const css::uno::Reference<ListenerT>& listener ) const
256
0
        {
257
0
            (listener.get()->*m_pMethod)( m_rEvent );
258
0
        }
Unexecuted instantiation: comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::container::XContainerListener, com::sun::star::container::ContainerEvent>::operator()(com::sun::star::uno::Reference<com::sun::star::container::XContainerListener> const&) const
Unexecuted instantiation: comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::linguistic2::XLinguServiceEventListener, com::sun::star::linguistic2::LinguServiceEvent>::operator()(com::sun::star::uno::Reference<com::sun::star::linguistic2::XLinguServiceEventListener> const&) const
Unexecuted instantiation: comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::linguistic2::XDictionaryListEventListener, com::sun::star::linguistic2::DictionaryListEvent>::operator()(com::sun::star::uno::Reference<com::sun::star::linguistic2::XDictionaryListEventListener> const&) const
259
    };
260
};
261
262
template <typename ListenerT, typename FuncT>
263
inline void OInterfaceContainerHelper2::forEach( FuncT const& func )
264
0
{
265
0
    OInterfaceIteratorHelper2 iter( *this );
266
0
    while (iter.hasMoreElements()) {
267
0
        css::uno::Reference<ListenerT> const xListener( iter.next(), css::uno::UNO_QUERY );
268
0
        if (xListener.is()) {
269
0
            try {
270
0
                func( xListener );
271
0
            }
272
0
            catch (css::lang::DisposedException const& exc) {
273
0
                if (exc.Context == xListener)
274
0
                    iter.remove();
275
0
            }
276
0
        }
277
0
    }
278
0
}
Unexecuted instantiation: definitioncontainer.cxx:void comphelper::OInterfaceContainerHelper2::forEach<com::sun::star::container::XContainerApproveListener, dbaccess::(anonymous namespace)::RaiseExceptionFromVeto>(dbaccess::(anonymous namespace)::RaiseExceptionFromVeto const&)
Unexecuted instantiation: void comphelper::OInterfaceContainerHelper2::forEach<com::sun::star::container::XContainerListener, comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::container::XContainerListener, com::sun::star::container::ContainerEvent> >(comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::container::XContainerListener, com::sun::star::container::ContainerEvent> const&)
Unexecuted instantiation: void comphelper::OInterfaceContainerHelper2::forEach<com::sun::star::linguistic2::XLinguServiceEventListener, comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::linguistic2::XLinguServiceEventListener, com::sun::star::linguistic2::LinguServiceEvent> >(comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::linguistic2::XLinguServiceEventListener, com::sun::star::linguistic2::LinguServiceEvent> const&)
Unexecuted instantiation: void comphelper::OInterfaceContainerHelper2::forEach<com::sun::star::linguistic2::XDictionaryListEventListener, comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::linguistic2::XDictionaryListEventListener, com::sun::star::linguistic2::DictionaryListEvent> >(comphelper::OInterfaceContainerHelper2::NotifySingleListener<com::sun::star::linguistic2::XDictionaryListEventListener, com::sun::star::linguistic2::DictionaryListEvent> const&)
Unexecuted instantiation: olemisc.cxx:void comphelper::OInterfaceContainerHelper2::forEach<com::sun::star::document::XEventListener, OleEmbeddedObject::MakeEventListenerNotification_Impl(rtl::OUString const&, osl::ResettableGuard<osl::Mutex>&)::$_0>(OleEmbeddedObject::MakeEventListenerNotification_Impl(rtl::OUString const&, osl::ResettableGuard<osl::Mutex>&)::$_0 const&)
279
280
template< typename ListenerT, typename EventT >
281
inline void OInterfaceContainerHelper2::notifyEach( void ( SAL_CALL ListenerT::*NotificationMethod )( const EventT& ), const EventT& Event )
282
0
{
283
0
    forEach< ListenerT, NotifySingleListener< ListenerT, EventT > >( NotifySingleListener< ListenerT, EventT >( NotificationMethod, Event ) );
284
0
}
Unexecuted instantiation: void comphelper::OInterfaceContainerHelper2::notifyEach<com::sun::star::container::XContainerListener, com::sun::star::container::ContainerEvent>(void (com::sun::star::container::XContainerListener::*)(com::sun::star::container::ContainerEvent const&), com::sun::star::container::ContainerEvent const&)
Unexecuted instantiation: void comphelper::OInterfaceContainerHelper2::notifyEach<com::sun::star::linguistic2::XLinguServiceEventListener, com::sun::star::linguistic2::LinguServiceEvent>(void (com::sun::star::linguistic2::XLinguServiceEventListener::*)(com::sun::star::linguistic2::LinguServiceEvent const&), com::sun::star::linguistic2::LinguServiceEvent const&)
Unexecuted instantiation: void comphelper::OInterfaceContainerHelper2::notifyEach<com::sun::star::linguistic2::XDictionaryListEventListener, com::sun::star::linguistic2::DictionaryListEvent>(void (com::sun::star::linguistic2::XDictionaryListEventListener::*)(com::sun::star::linguistic2::DictionaryListEvent const&), com::sun::star::linguistic2::DictionaryListEvent const&)
285
286
}
287
#endif
288
289
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */