Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/comphelper/multiinterfacecontainer4.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
#pragma once
20
#include <sal/config.h>
21
#include <comphelper/interfacecontainer4.hxx>
22
#include <memory>
23
#include <mutex>
24
#include <vector>
25
26
namespace com::sun::star::lang
27
{
28
struct EventObject;
29
}
30
31
/** */ //for docpp
32
namespace comphelper
33
{
34
/**
35
  A helper class to store interface references of different types.
36
  This is a copy of the code at include/comphelper/multiinterfacecontainer3.hxx,
37
  except that it (a) uses std::mutex instead of osl::Mutex and (b) does not
38
  store a reference to the mutex, but relies on the calling class to take
39
  a lock around using it.
40
  @see OInterfaceIteratorHelper3
41
  @see OInterfaceContainerHelper3
42
 */
43
template <class key, class listener, class equalImpl = std::equal_to<key>>
44
class OMultiTypeInterfaceContainerHelperVar4
45
{
46
public:
47
435k
    OMultiTypeInterfaceContainerHelperVar4() {}
comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<int> >::OMultiTypeInterfaceContainerHelperVar4()
Line
Count
Source
47
81.3k
    OMultiTypeInterfaceContainerHelperVar4() {}
comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<int> >::OMultiTypeInterfaceContainerHelperVar4()
Line
Count
Source
47
81.3k
    OMultiTypeInterfaceContainerHelperVar4() {}
comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::frame::XStatusListener, std::__1::equal_to<rtl::OUString> >::OMultiTypeInterfaceContainerHelperVar4()
Line
Count
Source
47
683
    OMultiTypeInterfaceContainerHelperVar4() {}
comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<rtl::OUString> >::OMultiTypeInterfaceContainerHelperVar4()
Line
Count
Source
47
217k
    OMultiTypeInterfaceContainerHelperVar4() {}
comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<rtl::OUString> >::OMultiTypeInterfaceContainerHelperVar4()
Line
Count
Source
47
54.4k
    OMultiTypeInterfaceContainerHelperVar4() {}
48
    /**
49
      Return all id's under which at least one interface is added.
50
     */
51
    inline std::vector<key> getContainedTypes(std::unique_lock<std::mutex>& rGuard) const
52
704
    {
53
704
        assert(rGuard.owns_lock());
54
704
        std::vector<key> aInterfaceTypes;
55
704
        aInterfaceTypes.reserve(m_aMap.size());
56
704
        for (const auto& rPair : m_aMap)
57
            // are interfaces added to this container?
58
0
            if (rPair.second->getLength(rGuard))
59
                // yes, put the type in the array
60
0
                aInterfaceTypes.push_back(rPair.first);
61
704
        return aInterfaceTypes;
62
704
    }
63
    inline bool hasContainedTypes(std::unique_lock<std::mutex>& rGuard) const
64
0
    {
65
0
        assert(rGuard.owns_lock());
66
0
        for (const auto& rPair : m_aMap)
67
            // are interfaces added to this container?
68
0
            if (rPair.second->getLength(rGuard))
69
0
                return true;
70
0
        return false;
71
0
    }
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<rtl::OUString> >::hasContainedTypes(std::__1::unique_lock<std::__1::mutex>&) const
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<rtl::OUString> >::hasContainedTypes(std::__1::unique_lock<std::__1::mutex>&) const
72
    /**
73
      Return the container created under this key.
74
      The InterfaceContainerHelper exists until the whole MultiTypeContainer is destroyed.
75
      @return the container created under this key. If the container
76
                 was not created, null was returned.
77
     */
78
    inline OInterfaceContainerHelper4<listener>* getContainer(std::unique_lock<std::mutex>& rGuard,
79
                                                              const key& rKey) const
80
628k
    {
81
628k
        auto iter = find(rGuard, rKey);
82
628k
        if (iter != m_aMap.end())
83
0
            return (*iter).second.get();
84
628k
        return nullptr;
85
628k
    }
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<int> >::getContainer(std::__1::unique_lock<std::__1::mutex>&, int const&) const
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<int> >::getContainer(std::__1::unique_lock<std::__1::mutex>&, int const&) const
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::frame::XStatusListener, std::__1::equal_to<rtl::OUString> >::getContainer(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&) const
comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<rtl::OUString> >::getContainer(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&) const
Line
Count
Source
80
628k
    {
81
628k
        auto iter = find(rGuard, rKey);
82
628k
        if (iter != m_aMap.end())
83
0
            return (*iter).second.get();
84
628k
        return nullptr;
85
628k
    }
86
    /** Inserts an element into the container with the specified key.
87
        The position is not specified, thus it is not specified in which order events are fired.
88
        @attention
89
        If you add the same interface more than once, then it will be added to the elements list
90
        more than once and thus if you want to remove that interface from the list, you have to call
91
        removeInterface() the same number of times.
92
        In the latter case, you will also get events fired more than once (if the interface is a
93
        listener interface).
94
        @param rKey
95
               the id of the container
96
        @param r
97
               interface to be added; it is allowed, to insert null or
98
               the same interface more than once
99
        @return
100
                the new count of elements in the container
101
    */
102
    inline sal_Int32 addInterface(::std::unique_lock<::std::mutex>& rGuard, const key& rKey,
103
                                  const css::uno::Reference<listener>& rListener)
104
0
    {
105
0
        auto iter = find(rGuard, rKey);
106
0
        if (iter == m_aMap.end())
107
0
        {
108
0
            auto pLC = new OInterfaceContainerHelper4<listener>();
109
0
            m_aMap.emplace_back(rKey, pLC);
110
0
            return pLC->addInterface(rGuard, rListener);
111
0
        }
112
0
        else
113
0
            return (*iter).second->addInterface(rGuard, rListener);
114
0
    }
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<int> >::addInterface(std::__1::unique_lock<std::__1::mutex>&, int const&, com::sun::star::uno::Reference<com::sun::star::beans::XPropertyChangeListener> const&)
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<int> >::addInterface(std::__1::unique_lock<std::__1::mutex>&, int const&, com::sun::star::uno::Reference<com::sun::star::beans::XVetoableChangeListener> const&)
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::frame::XStatusListener, std::__1::equal_to<rtl::OUString> >::addInterface(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::frame::XStatusListener> const&)
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<rtl::OUString> >::addInterface(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::beans::XPropertyChangeListener> const&)
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<rtl::OUString> >::addInterface(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::beans::XVetoableChangeListener> const&)
115
    /** Removes an element from the container with the specified key.
116
        It uses interface equality to remove the interface.
117
        @param rKey
118
               the id of the container
119
        @param rxIFace
120
               interface to be removed
121
        @return
122
                the new count of elements in the container
123
    */
124
    inline sal_Int32 removeInterface(::std::unique_lock<::std::mutex>& rGuard, const key& rKey,
125
                                     const css::uno::Reference<listener>& rListener)
126
0
    {
127
        // search container with id nUik
128
0
        auto iter = find(rGuard, rKey);
129
        // container found?
130
0
        if (iter != m_aMap.end())
131
0
            return (*iter).second->removeInterface(rGuard, rListener);
132
        // no container with this id. Always return 0
133
0
        return 0;
134
0
    }
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<int> >::removeInterface(std::__1::unique_lock<std::__1::mutex>&, int const&, com::sun::star::uno::Reference<com::sun::star::beans::XPropertyChangeListener> const&)
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<int> >::removeInterface(std::__1::unique_lock<std::__1::mutex>&, int const&, com::sun::star::uno::Reference<com::sun::star::beans::XVetoableChangeListener> const&)
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::frame::XStatusListener, std::__1::equal_to<rtl::OUString> >::removeInterface(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::frame::XStatusListener> const&)
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<rtl::OUString> >::removeInterface(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::beans::XPropertyChangeListener> const&)
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<rtl::OUString> >::removeInterface(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::beans::XVetoableChangeListener> const&)
135
    /**
136
      Call disposing on all references in the container, that
137
      support XEventListener. Then clears the container.
138
      @param rEvt the event object which is passed during disposing() call
139
     */
140
    inline void disposeAndClear(std::unique_lock<std::mutex>& rGuard,
141
                                const css::lang::EventObject& rEvt)
142
93.7k
    {
143
93.7k
        assert(rGuard.owns_lock());
144
        // create a copy, because do not fire event in a guarded section
145
93.7k
        InterfaceMap tempMap;
146
93.7k
        {
147
93.7k
            tempMap = std::move(m_aMap);
148
93.7k
        }
149
93.7k
        rGuard.unlock();
150
        // So... we don't want to hold the normal mutex while we fire
151
        // the events, but the calling convention here wants a mutex, so
152
        // just create a temporary/fake one. Since the listeners we
153
        // are working with are now function-local, we don't really need
154
        // a mutex at all, but it's easier to create a fake one than
155
        // create a bunch of special-case code for this situation.
156
93.7k
        std::mutex tempMutex;
157
93.7k
        std::unique_lock tempGuard(tempMutex);
158
93.7k
        for (auto& rPair : tempMap)
159
0
        {
160
0
            OInterfaceIteratorHelper4<listener> aIt(tempGuard, *rPair.second);
161
0
            while (aIt.hasMoreElements())
162
0
            {
163
0
                try
164
0
                {
165
0
                    aIt.next()->disposing(rEvt);
166
0
                }
167
0
                catch (css::uno::RuntimeException&)
168
0
                {
169
                    // be robust, if e.g. a remote bridge has disposed already.
170
                    // there is no way to delegate the error to the caller :o(.
171
0
                }
172
0
            }
173
0
        }
174
93.7k
        rGuard.lock(); // return with lock in same state as entry
175
93.7k
    }
comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<int> >::disposeAndClear(std::__1::unique_lock<std::__1::mutex>&, com::sun::star::lang::EventObject const&)
Line
Count
Source
142
45.1k
    {
143
45.1k
        assert(rGuard.owns_lock());
144
        // create a copy, because do not fire event in a guarded section
145
45.1k
        InterfaceMap tempMap;
146
45.1k
        {
147
45.1k
            tempMap = std::move(m_aMap);
148
45.1k
        }
149
45.1k
        rGuard.unlock();
150
        // So... we don't want to hold the normal mutex while we fire
151
        // the events, but the calling convention here wants a mutex, so
152
        // just create a temporary/fake one. Since the listeners we
153
        // are working with are now function-local, we don't really need
154
        // a mutex at all, but it's easier to create a fake one than
155
        // create a bunch of special-case code for this situation.
156
45.1k
        std::mutex tempMutex;
157
45.1k
        std::unique_lock tempGuard(tempMutex);
158
45.1k
        for (auto& rPair : tempMap)
159
0
        {
160
0
            OInterfaceIteratorHelper4<listener> aIt(tempGuard, *rPair.second);
161
0
            while (aIt.hasMoreElements())
162
0
            {
163
0
                try
164
0
                {
165
0
                    aIt.next()->disposing(rEvt);
166
0
                }
167
0
                catch (css::uno::RuntimeException&)
168
0
                {
169
                    // be robust, if e.g. a remote bridge has disposed already.
170
                    // there is no way to delegate the error to the caller :o(.
171
0
                }
172
0
            }
173
0
        }
174
45.1k
        rGuard.lock(); // return with lock in same state as entry
175
45.1k
    }
comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<int> >::disposeAndClear(std::__1::unique_lock<std::__1::mutex>&, com::sun::star::lang::EventObject const&)
Line
Count
Source
142
45.1k
    {
143
45.1k
        assert(rGuard.owns_lock());
144
        // create a copy, because do not fire event in a guarded section
145
45.1k
        InterfaceMap tempMap;
146
45.1k
        {
147
45.1k
            tempMap = std::move(m_aMap);
148
45.1k
        }
149
45.1k
        rGuard.unlock();
150
        // So... we don't want to hold the normal mutex while we fire
151
        // the events, but the calling convention here wants a mutex, so
152
        // just create a temporary/fake one. Since the listeners we
153
        // are working with are now function-local, we don't really need
154
        // a mutex at all, but it's easier to create a fake one than
155
        // create a bunch of special-case code for this situation.
156
45.1k
        std::mutex tempMutex;
157
45.1k
        std::unique_lock tempGuard(tempMutex);
158
45.1k
        for (auto& rPair : tempMap)
159
0
        {
160
0
            OInterfaceIteratorHelper4<listener> aIt(tempGuard, *rPair.second);
161
0
            while (aIt.hasMoreElements())
162
0
            {
163
0
                try
164
0
                {
165
0
                    aIt.next()->disposing(rEvt);
166
0
                }
167
0
                catch (css::uno::RuntimeException&)
168
0
                {
169
                    // be robust, if e.g. a remote bridge has disposed already.
170
                    // there is no way to delegate the error to the caller :o(.
171
0
                }
172
0
            }
173
0
        }
174
45.1k
        rGuard.lock(); // return with lock in same state as entry
175
45.1k
    }
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::frame::XStatusListener, std::__1::equal_to<rtl::OUString> >::disposeAndClear(std::__1::unique_lock<std::__1::mutex>&, com::sun::star::lang::EventObject const&)
comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<rtl::OUString> >::disposeAndClear(std::__1::unique_lock<std::__1::mutex>&, com::sun::star::lang::EventObject const&)
Line
Count
Source
142
3.44k
    {
143
3.44k
        assert(rGuard.owns_lock());
144
        // create a copy, because do not fire event in a guarded section
145
3.44k
        InterfaceMap tempMap;
146
3.44k
        {
147
3.44k
            tempMap = std::move(m_aMap);
148
3.44k
        }
149
3.44k
        rGuard.unlock();
150
        // So... we don't want to hold the normal mutex while we fire
151
        // the events, but the calling convention here wants a mutex, so
152
        // just create a temporary/fake one. Since the listeners we
153
        // are working with are now function-local, we don't really need
154
        // a mutex at all, but it's easier to create a fake one than
155
        // create a bunch of special-case code for this situation.
156
3.44k
        std::mutex tempMutex;
157
3.44k
        std::unique_lock tempGuard(tempMutex);
158
3.44k
        for (auto& rPair : tempMap)
159
0
        {
160
0
            OInterfaceIteratorHelper4<listener> aIt(tempGuard, *rPair.second);
161
0
            while (aIt.hasMoreElements())
162
0
            {
163
0
                try
164
0
                {
165
0
                    aIt.next()->disposing(rEvt);
166
0
                }
167
0
                catch (css::uno::RuntimeException&)
168
0
                {
169
                    // be robust, if e.g. a remote bridge has disposed already.
170
                    // there is no way to delegate the error to the caller :o(.
171
0
                }
172
0
            }
173
0
        }
174
3.44k
        rGuard.lock(); // return with lock in same state as entry
175
3.44k
    }
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<rtl::OUString> >::disposeAndClear(std::__1::unique_lock<std::__1::mutex>&, com::sun::star::lang::EventObject const&)
176
    /**
177
      Remove all elements of all containers. Does not delete the container.
178
     */
179
    inline void clear(std::unique_lock<std::mutex>& rGuard)
180
    {
181
        assert(rGuard.owns_lock());
182
        (void)rGuard;
183
        for (const auto& rPair : m_aMap)
184
            rPair.second->clear();
185
    }
186
    typedef key keyType;
187
188
private:
189
    typedef ::std::vector<std::pair<key, std::unique_ptr<OInterfaceContainerHelper4<listener>>>>
190
        InterfaceMap;
191
    InterfaceMap m_aMap;
192
    typename InterfaceMap::const_iterator find(std::unique_lock<std::mutex>& rGuard,
193
                                               const key& rKey) const
194
628k
    {
195
628k
        assert(rGuard.owns_lock());
196
628k
        (void)rGuard;
197
628k
        auto iter = m_aMap.begin();
198
628k
        auto end = m_aMap.end();
199
628k
        while (iter != end)
200
0
        {
201
0
            equalImpl equal;
202
0
            if (equal(iter->first, rKey))
203
0
                break;
204
0
            ++iter;
205
0
        }
206
628k
        return iter;
207
628k
    }
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<int> >::find(std::__1::unique_lock<std::__1::mutex>&, int const&) const
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<int> >::find(std::__1::unique_lock<std::__1::mutex>&, int const&) const
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::frame::XStatusListener, std::__1::equal_to<rtl::OUString> >::find(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&) const
comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<rtl::OUString> >::find(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&) const
Line
Count
Source
194
628k
    {
195
628k
        assert(rGuard.owns_lock());
196
628k
        (void)rGuard;
197
628k
        auto iter = m_aMap.begin();
198
628k
        auto end = m_aMap.end();
199
628k
        while (iter != end)
200
0
        {
201
0
            equalImpl equal;
202
0
            if (equal(iter->first, rKey))
203
0
                break;
204
0
            ++iter;
205
0
        }
206
628k
        return iter;
207
628k
    }
Unexecuted instantiation: comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<rtl::OUString> >::find(std::__1::unique_lock<std::__1::mutex>&, rtl::OUString const&) const
208
    OMultiTypeInterfaceContainerHelperVar4(const OMultiTypeInterfaceContainerHelperVar4&) = delete;
209
    OMultiTypeInterfaceContainerHelperVar4& operator=(const OMultiTypeInterfaceContainerHelperVar4&)
210
        = delete;
211
};
212
} // namespace comphelper
213
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */