1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
21 #include <com/sun/star/lang/EventObject.hpp>
22 #include <comphelper/interfacecontainer4.hxx>
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
38 template <class key
, class listener
, class equalImpl
= std::equal_to
<key
>>
39 class OMultiTypeInterfaceContainerHelperVar4
42 OMultiTypeInterfaceContainerHelperVar4() {}
44 Return all id's under which at least one interface is added.
46 inline std::vector
<key
> getContainedTypes(std::unique_lock
<std::mutex
>& rGuard
) const
48 assert(rGuard
.owns_lock());
49 std::vector
<key
> aInterfaceTypes
;
50 aInterfaceTypes
.reserve(m_aMap
.size());
51 for (const auto& rPair
: m_aMap
)
52 // are interfaces added to this container?
53 if (rPair
.second
->getLength(rGuard
))
54 // yes, put the type in the array
55 aInterfaceTypes
.push_back(rPair
.first
);
56 return aInterfaceTypes
;
58 inline bool hasContainedTypes(std::unique_lock
<std::mutex
>& rGuard
) const
60 assert(rGuard
.owns_lock());
61 for (const auto& rPair
: m_aMap
)
62 // are interfaces added to this container?
63 if (rPair
.second
->getLength(rGuard
))
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.
73 inline OInterfaceContainerHelper4
<listener
>* getContainer(std::unique_lock
<std::mutex
>& rGuard
,
74 const key
& rKey
) const
76 auto iter
= find(rGuard
, rKey
);
77 if (iter
!= m_aMap
.end())
78 return (*iter
).second
.get();
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.
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
90 the id of the container
92 interface to be added; it is allowed, to insert null or
93 the same interface more than once
95 the new count of elements in the container
97 inline sal_Int32
addInterface(::std::unique_lock
<::std::mutex
>& rGuard
, const key
& rKey
,
98 const css::uno::Reference
<listener
>& rListener
)
100 auto iter
= find(rGuard
, rKey
);
101 if (iter
== m_aMap
.end())
103 auto pLC
= new OInterfaceContainerHelper4
<listener
>();
104 m_aMap
.emplace_back(rKey
, pLC
);
105 return pLC
->addInterface(rGuard
, rListener
);
108 return (*iter
).second
->addInterface(rGuard
, rListener
);
110 /** Removes an element from the container with the specified key.
111 It uses interface equality to remove the interface.
113 the id of the container
115 interface to be removed
117 the new count of elements in the container
119 inline sal_Int32
removeInterface(::std::unique_lock
<::std::mutex
>& rGuard
, const key
& rKey
,
120 const css::uno::Reference
<listener
>& rListener
)
122 // search container with id nUik
123 auto iter
= find(rGuard
, rKey
);
125 if (iter
!= m_aMap
.end())
126 return (*iter
).second
->removeInterface(rGuard
, rListener
);
127 // no container with this id. Always return 0
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
135 inline void disposeAndClear(std::unique_lock
<std::mutex
>& rGuard
,
136 const css::lang::EventObject
& rEvt
)
138 assert(rGuard
.owns_lock());
139 // create a copy, because do not fire event in a guarded section
140 InterfaceMap tempMap
;
142 tempMap
= std::move(m_aMap
);
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 std::mutex tempMutex
;
152 std::unique_lock
tempGuard(tempMutex
);
153 for (auto& rPair
: tempMap
)
155 OInterfaceIteratorHelper4
<listener
> aIt(tempGuard
, *rPair
.second
);
156 while (aIt
.hasMoreElements())
160 aIt
.next()->disposing(rEvt
);
162 catch (css::uno::RuntimeException
&)
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(.
169 rGuard
.lock(); // return with lock in same state as entry
172 Remove all elements of all containers. Does not delete the container.
174 inline void clear(std::unique_lock
<std::mutex
>& rGuard
)
176 assert(rGuard
.owns_lock());
178 for (const auto& rPair
: m_aMap
)
179 rPair
.second
->clear();
184 typedef ::std::vector
<std::pair
<key
, std::unique_ptr
<OInterfaceContainerHelper4
<listener
>>>>
187 typename
InterfaceMap::const_iterator
find(std::unique_lock
<std::mutex
>& rGuard
,
188 const key
& rKey
) const
190 assert(rGuard
.owns_lock());
192 auto iter
= m_aMap
.begin();
193 auto end
= m_aMap
.end();
197 if (equal(iter
->first
, rKey
))
203 OMultiTypeInterfaceContainerHelperVar4(const OMultiTypeInterfaceContainerHelperVar4
&) = delete;
204 OMultiTypeInterfaceContainerHelperVar4
& operator=(const OMultiTypeInterfaceContainerHelperVar4
&)
207 } // namespace comphelper
208 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */