1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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/.
10 #include <compbase2.hxx>
11 #include <sal/log.hxx>
12 #include <osl/diagnose.h>
16 WeakComponentImplHelperBase2::~WeakComponentImplHelperBase2() {}
18 // css::lang::XComponent
19 void SAL_CALL
WeakComponentImplHelperBase2::dispose()
21 std::unique_lock
aGuard(m_aMutex
);
26 if (!aGuard
.owns_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
);
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())
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?
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!");
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;
115 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
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:
134 for (sal_Int32 i
= 0; i
< type
->nBaseTypes
; ++i
)
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
),
149 // Profiling showed that it is important to speed up the common case
151 if (type
->nBaseTypes
== 1)
156 if (recursivelyFindType(demandedType
, base
, offset
))
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
;
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
);
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
);
197 return makeInterface(offset
, that
);
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
);
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
);
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: */