Coverage Report

Created: 2026-06-30 11:14

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
715k
    OMultiTypeInterfaceContainerHelperVar4() {}
comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<int> >::OMultiTypeInterfaceContainerHelperVar4()
Line
Count
Source
47
91.8k
    OMultiTypeInterfaceContainerHelperVar4() {}
comphelper::OMultiTypeInterfaceContainerHelperVar4<int, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<int> >::OMultiTypeInterfaceContainerHelperVar4()
Line
Count
Source
47
91.8k
    OMultiTypeInterfaceContainerHelperVar4() {}
comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::frame::XStatusListener, std::__1::equal_to<rtl::OUString> >::OMultiTypeInterfaceContainerHelperVar4()
Line
Count
Source
47
26
    OMultiTypeInterfaceContainerHelperVar4() {}
comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XPropertyChangeListener, std::__1::equal_to<rtl::OUString> >::OMultiTypeInterfaceContainerHelperVar4()
Line
Count
Source
47
470k
    OMultiTypeInterfaceContainerHelperVar4() {}
comphelper::OMultiTypeInterfaceContainerHelperVar4<rtl::OUString, com::sun::star::beans::XVetoableChangeListener, std::__1::equal_to<rtl::OUString> >::OMultiTypeInterfaceContainerHelperVar4()
Line
Count
Source
47
61.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
0
    {
53
0
        assert(rGuard.owns_lock());
54
0
        std::vector<key> aInterfaceTypes;
55
0
        aInterfaceTypes.reserve(m_aMap.size());
56
0
        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
0
        return aInterfaceTypes;
62
0
    }
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
696k
    {
81
696k
        auto iter = find(rGuard, rKey);
82
696k
        if (iter != m_aMap.end())
83
0
            return (*iter).second.get();
84
696k
        return nullptr;
85
696k
    }
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
696k
    {
81
696k
        auto iter = find(rGuard, rKey);
82
696k
        if (iter != m_aMap.end())
83
0
            return (*iter).second.get();
84
696k
        return nullptr;
85
696k
    }
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
111k
    {
143
111k
        assert(rGuard.owns_lock());
144
        // create a copy, because do not fire event in a guarded section
145
111k
        InterfaceMap tempMap;
146
111k
        {
147
111k
            tempMap = std::move(m_aMap);
148
111k
        }
149
111k
        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
111k
        std::mutex tempMutex;
157
111k
        std::unique_lock tempGuard(tempMutex);
158
111k
        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
111k
        rGuard.lock(); // return with lock in same state as entry
175
111k
    }
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
51.0k
    {
143
51.0k
        assert(rGuard.owns_lock());
144
        // create a copy, because do not fire event in a guarded section
145
51.0k
        InterfaceMap tempMap;
146
51.0k
        {
147
51.0k
            tempMap = std::move(m_aMap);
148
51.0k
        }
149
51.0k
        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
51.0k
        std::mutex tempMutex;
157
51.0k
        std::unique_lock tempGuard(tempMutex);
158
51.0k
        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
51.0k
        rGuard.lock(); // return with lock in same state as entry
175
51.0k
    }
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
51.0k
    {
143
51.0k
        assert(rGuard.owns_lock());
144
        // create a copy, because do not fire event in a guarded section
145
51.0k
        InterfaceMap tempMap;
146
51.0k
        {
147
51.0k
            tempMap = std::move(m_aMap);
148
51.0k
        }
149
51.0k
        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
51.0k
        std::mutex tempMutex;
157
51.0k
        std::unique_lock tempGuard(tempMutex);
158
51.0k
        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
51.0k
        rGuard.lock(); // return with lock in same state as entry
175
51.0k
    }
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
9.43k
    {
143
9.43k
        assert(rGuard.owns_lock());
144
        // create a copy, because do not fire event in a guarded section
145
9.43k
        InterfaceMap tempMap;
146
9.43k
        {
147
9.43k
            tempMap = std::move(m_aMap);
148
9.43k
        }
149
9.43k
        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
9.43k
        std::mutex tempMutex;
157
9.43k
        std::unique_lock tempGuard(tempMutex);
158
9.43k
        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
9.43k
        rGuard.lock(); // return with lock in same state as entry
175
9.43k
    }
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
696k
    {
195
696k
        assert(rGuard.owns_lock());
196
696k
        (void)rGuard;
197
696k
        auto iter = m_aMap.begin();
198
696k
        auto end = m_aMap.end();
199
696k
        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
696k
        return iter;
207
696k
    }
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
696k
    {
195
696k
        assert(rGuard.owns_lock());
196
696k
        (void)rGuard;
197
696k
        auto iter = m_aMap.begin();
198
696k
        auto end = m_aMap.end();
199
696k
        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
696k
        return iter;
207
696k
    }
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: */