Coverage Report

Created: 2025-07-07 10:01

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