Bump version to 24.04.3.4
[LibreOffice.git] / cppuhelper / source / compbase.cxx
blobed4909b711069c41c78c9262d1aca239683174c2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
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/.
8 */
10 #include <compbase2.hxx>
11 #include <sal/log.hxx>
12 #include <osl/diagnose.h>
14 namespace cppuhelper
16 WeakComponentImplHelperBase2::~WeakComponentImplHelperBase2() {}
18 // css::lang::XComponent
19 void SAL_CALL WeakComponentImplHelperBase2::dispose()
21 std::unique_lock aGuard(m_aMutex);
22 if (m_bDisposed)
23 return;
24 m_bDisposed = true;
25 disposing(aGuard);
26 if (!aGuard.owns_lock())
27 aGuard.lock();
28 css::lang::EventObject aEvt(static_cast<OWeakObject*>(this));
29 maEventListeners.disposeAndClear(aGuard, aEvt);
32 void WeakComponentImplHelperBase2::disposing(std::unique_lock<std::mutex>&) {}
34 void SAL_CALL WeakComponentImplHelperBase2::addEventListener(
35 css::uno::Reference<css::lang::XEventListener> const& rxListener)
37 std::unique_lock aGuard(m_aMutex);
38 if (m_bDisposed)
39 return;
40 maEventListeners.addInterface(aGuard, rxListener);
43 void SAL_CALL WeakComponentImplHelperBase2::removeEventListener(
44 css::uno::Reference<css::lang::XEventListener> const& rxListener)
46 std::unique_lock aGuard(m_aMutex);
47 maEventListeners.removeInterface(aGuard, rxListener);
50 css::uno::Any SAL_CALL WeakComponentImplHelperBase2::queryInterface(css::uno::Type const& rType)
52 css::uno::Any aReturn = ::cppu::queryInterface(rType, static_cast<css::uno::XWeak*>(this),
53 static_cast<css::lang::XComponent*>(this));
54 if (aReturn.hasValue())
55 return aReturn;
56 return OWeakObject::queryInterface(rType);
59 static void checkInterface(css::uno::Type const& rType)
61 if (css::uno::TypeClass_INTERFACE != rType.getTypeClass())
63 OUString msg("querying for interface \"" + rType.getTypeName() + "\": no interface type!");
64 SAL_WARN("cppuhelper", msg);
65 throw css::uno::RuntimeException(msg);
69 static bool isXInterface(rtl_uString* pStr)
71 return OUString::unacquired(&pStr) == "com.sun.star.uno.XInterface";
74 static bool td_equals(typelib_TypeDescriptionReference const* pTDR1,
75 typelib_TypeDescriptionReference const* pTDR2)
77 return ((pTDR1 == pTDR2)
78 || OUString::unacquired(&pTDR1->pTypeName) == OUString::unacquired(&pTDR2->pTypeName));
81 static cppu::type_entry* getTypeEntries(cppu::class_data* cd)
83 cppu::type_entry* pEntries = cd->m_typeEntries;
84 if (!cd->m_storedTypeRefs) // not inited?
86 static std::mutex aMutex;
87 std::scoped_lock guard(aMutex);
88 if (!cd->m_storedTypeRefs) // not inited?
90 // get all types
91 for (sal_Int32 n = cd->m_nTypes; n--;)
93 cppu::type_entry* pEntry = &pEntries[n];
94 css::uno::Type const& rType = (*pEntry->m_type.getCppuType)(nullptr);
95 OSL_ENSURE(rType.getTypeClass() == css::uno::TypeClass_INTERFACE,
96 "### wrong helper init: expected interface!");
97 OSL_ENSURE(
98 !isXInterface(rType.getTypeLibType()->pTypeName),
99 "### want to implement XInterface: template argument is XInterface?!?!?!");
100 if (rType.getTypeClass() != css::uno::TypeClass_INTERFACE)
102 OUString msg("type \"" + rType.getTypeName() + "\" is no interface type!");
103 SAL_WARN("cppuhelper", msg);
104 throw css::uno::RuntimeException(msg);
106 // ref is statically held by getCppuType()
107 pEntry->m_type.typeRef = rType.getTypeLibType();
109 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
110 cd->m_storedTypeRefs = true;
113 else
115 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
117 return pEntries;
120 static void* makeInterface(sal_IntPtr nOffset, void* that)
122 return (static_cast<char*>(that) + nOffset);
125 static bool recursivelyFindType(typelib_TypeDescriptionReference const* demandedType,
126 typelib_InterfaceTypeDescription const* type, sal_IntPtr* offset)
128 // This code assumes that the vtables of a multiple-inheritance class (the
129 // offset amount by which to adjust the this pointer) follow one another in
130 // the object layout, and that they contain slots for the inherited classes
131 // in a specific order. In theory, that need not hold for any given
132 // platform; in practice, it seems to work well on all supported platforms:
133 next:
134 for (sal_Int32 i = 0; i < type->nBaseTypes; ++i)
136 if (i > 0)
138 *offset += sizeof(void*);
140 typelib_InterfaceTypeDescription const* base = type->ppBaseTypes[i];
141 // ignore XInterface:
142 if (base->nBaseTypes > 0)
144 if (td_equals(reinterpret_cast<typelib_TypeDescriptionReference const*>(base),
145 demandedType))
147 return true;
149 // Profiling showed that it is important to speed up the common case
150 // of only one base:
151 if (type->nBaseTypes == 1)
153 type = base;
154 goto next;
156 if (recursivelyFindType(demandedType, base, offset))
158 return true;
162 return false;
165 static void* queryDeepNoXInterface(typelib_TypeDescriptionReference const* pDemandedTDR,
166 cppu::class_data* cd, void* that)
168 cppu::type_entry* pEntries = getTypeEntries(cd);
169 sal_Int32 nTypes = cd->m_nTypes;
170 sal_Int32 n;
172 // try top interfaces without getting td
173 for (n = 0; n < nTypes; ++n)
175 if (td_equals(pEntries[n].m_type.typeRef, pDemandedTDR))
177 return makeInterface(pEntries[n].m_offset, that);
180 // query deep getting td
181 for (n = 0; n < nTypes; ++n)
183 typelib_TypeDescription* pTD = nullptr;
184 TYPELIB_DANGER_GET(&pTD, pEntries[n].m_type.typeRef);
185 if (pTD)
187 // exclude top (already tested) and bottom (XInterface) interface
188 OSL_ENSURE(reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD)->nBaseTypes > 0,
189 "### want to implement XInterface:"
190 " template argument is XInterface?!?!?!");
191 sal_IntPtr offset = pEntries[n].m_offset;
192 bool found = recursivelyFindType(
193 pDemandedTDR, reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD), &offset);
194 TYPELIB_DANGER_RELEASE(pTD);
195 if (found)
197 return makeInterface(offset, that);
200 else
202 OUString msg("cannot get type description for type \""
203 + OUString::unacquired(&pEntries[n].m_type.typeRef->pTypeName) + "\"!");
204 SAL_WARN("cppuhelper", msg);
205 throw css::uno::RuntimeException(msg);
208 return nullptr;
211 css::uno::Any WeakComponentImplHelper_query(css::uno::Type const& rType, cppu::class_data* cd,
212 WeakComponentImplHelperBase2* pBase)
214 checkInterface(rType);
215 typelib_TypeDescriptionReference* pTDR = rType.getTypeLibType();
217 // shortcut XInterface to WeakComponentImplHelperBase
218 if (!isXInterface(pTDR->pTypeName))
220 void* p = queryDeepNoXInterface(pTDR, cd, pBase);
221 if (p)
223 return css::uno::Any(&p, pTDR);
226 return pBase->cppuhelper::WeakComponentImplHelperBase2::queryInterface(rType);
229 } // namespace cppuextra
231 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */