Line data Source code
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 :
20 : #include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
21 :
22 : #include "guardedarray.hxx"
23 :
24 : #include "bridges/cpp_uno/shared/bridge.hxx"
25 : #include "bridges/cpp_uno/shared/vtablefactory.hxx"
26 :
27 : #include "com/sun/star/uno/XInterface.hpp"
28 : #include "osl/diagnose.h"
29 : #include "osl/getglobalmutex.hxx"
30 : #include "osl/interlck.h"
31 : #include "osl/mutex.hxx"
32 : #include "rtl/instance.hxx"
33 : #include "typelib/typedescription.h"
34 :
35 : #include <cstddef>
36 : #include <new>
37 :
38 :
39 : static bridges::cpp_uno::shared::VtableFactory * pInstance;
40 :
41 : #if defined(__GNUG__) && !defined(__MINGW32__)
42 : void dso_init(void) __attribute__((constructor));
43 : void dso_exit(void) __attribute__((destructor));
44 : #endif
45 :
46 257 : void dso_init(void) {
47 257 : if (!pInstance)
48 257 : pInstance = new bridges::cpp_uno::shared::VtableFactory();
49 257 : }
50 :
51 0 : void dso_exit(void) {
52 0 : if (pInstance)
53 : {
54 0 : delete pInstance;
55 0 : pInstance = NULL;
56 : }
57 0 : }
58 :
59 : #ifdef __SUNPRO_CC
60 : # pragma init(dso_init)
61 : # pragma fini(dso_exit)
62 : #endif
63 :
64 :
65 :
66 : namespace {
67 :
68 : struct InitVtableFactory {
69 18 : bridges::cpp_uno::shared::VtableFactory * operator()() {
70 18 : return pInstance;
71 : }
72 : };
73 :
74 1693 : bridges::cpp_uno::shared::VtableFactory * getVtableFactory() {
75 : return rtl_Instance<
76 : bridges::cpp_uno::shared::VtableFactory, InitVtableFactory,
77 : osl::MutexGuard, osl::GetGlobalMutex >::create(
78 1693 : InitVtableFactory(), osl::GetGlobalMutex());
79 : }
80 :
81 : }
82 :
83 : namespace bridges { namespace cpp_uno { namespace shared {
84 :
85 1693 : void freeCppInterfaceProxy(uno_ExtEnvironment * pEnv, void * pInterface)
86 : {
87 : CppInterfaceProxy * pThis = CppInterfaceProxy::castInterfaceToProxy(
88 1693 : pInterface);
89 1693 : if (pEnv != pThis->pBridge->getCppEnv()) {
90 : OSL_ASSERT(false);
91 : }
92 :
93 1693 : (*pThis->pBridge->getUnoEnv()->revokeInterface)(
94 1693 : pThis->pBridge->getUnoEnv(), pThis->pUnoI );
95 1693 : (*pThis->pUnoI->release)( pThis->pUnoI );
96 : ::typelib_typedescription_release(
97 1693 : (typelib_TypeDescription *)pThis->pTypeDescr );
98 1693 : pThis->pBridge->release();
99 :
100 : #if OSL_DEBUG_LEVEL > 1
101 : *(int *)pInterface = 0xdeadbabe;
102 : #endif
103 1693 : pThis->~CppInterfaceProxy();
104 1693 : delete[] reinterpret_cast< char * >(pThis);
105 1693 : }
106 :
107 1693 : com::sun::star::uno::XInterface * CppInterfaceProxy::create(
108 : bridges::cpp_uno::shared::Bridge * pBridge, uno_Interface * pUnoI,
109 : typelib_InterfaceTypeDescription * pTypeDescr, OUString const & rOId)
110 : SAL_THROW(())
111 : {
112 : typelib_typedescription_complete(
113 1693 : reinterpret_cast< typelib_TypeDescription ** >(&pTypeDescr));
114 : bridges::cpp_uno::shared::VtableFactory::Vtables aVtables(
115 1693 : getVtableFactory()->getVtables(pTypeDescr));
116 : bridges::cpp_uno::shared::GuardedArray< char > pMemory(
117 : new char[
118 : sizeof (CppInterfaceProxy)
119 1693 : + (aVtables.count - 1) * sizeof (void **)]);
120 1693 : new(pMemory.get()) CppInterfaceProxy(pBridge, pUnoI, pTypeDescr, rOId);
121 : CppInterfaceProxy * pProxy = reinterpret_cast< CppInterfaceProxy * >(
122 1693 : pMemory.release());
123 3400 : for (sal_Int32 i = 0; i < aVtables.count; ++i) {
124 : pProxy->vtables[i] = VtableFactory::mapBlockToVtable(
125 1707 : aVtables.blocks[i].start);
126 : }
127 1693 : return castProxyToInterface(pProxy);
128 : }
129 :
130 265 : void CppInterfaceProxy::acquireProxy() SAL_THROW(())
131 : {
132 265 : if (1 == osl_atomic_increment( &nRef ))
133 : {
134 : // rebirth of proxy zombie
135 : // register at cpp env
136 30 : void * pThis = castProxyToInterface( this );
137 30 : (*pBridge->getCppEnv()->registerProxyInterface)(
138 : pBridge->getCppEnv(), &pThis, freeCppInterfaceProxy, oid.pData,
139 30 : pTypeDescr );
140 : OSL_ASSERT( pThis == castProxyToInterface( this ) );
141 : }
142 265 : }
143 :
144 1958 : void CppInterfaceProxy::releaseProxy() SAL_THROW(())
145 : {
146 1958 : if (! osl_atomic_decrement( &nRef )) // last release
147 : {
148 : // revoke from cpp env
149 1723 : (*pBridge->getCppEnv()->revokeInterface)(
150 1723 : pBridge->getCppEnv(), castProxyToInterface( this ) );
151 : }
152 1958 : }
153 :
154 1693 : CppInterfaceProxy::CppInterfaceProxy(
155 : bridges::cpp_uno::shared::Bridge * pBridge_, uno_Interface * pUnoI_,
156 : typelib_InterfaceTypeDescription * pTypeDescr_, OUString const & rOId_)
157 : SAL_THROW(())
158 : : nRef( 1 )
159 : , pBridge( pBridge_ )
160 : , pUnoI( pUnoI_ )
161 : , pTypeDescr( pTypeDescr_ )
162 1693 : , oid( rOId_ )
163 : {
164 1693 : pBridge->acquire();
165 1693 : ::typelib_typedescription_acquire( (typelib_TypeDescription *)pTypeDescr );
166 1693 : (*pUnoI->acquire)( pUnoI );
167 1693 : (*pBridge->getUnoEnv()->registerInterface)(
168 : pBridge->getUnoEnv(), reinterpret_cast< void ** >( &pUnoI ), oid.pData,
169 1693 : pTypeDescr );
170 1693 : }
171 :
172 1693 : CppInterfaceProxy::~CppInterfaceProxy()
173 1693 : {}
174 :
175 3446 : com::sun::star::uno::XInterface * CppInterfaceProxy::castProxyToInterface(
176 : CppInterfaceProxy * pProxy)
177 : {
178 : return reinterpret_cast< com::sun::star::uno::XInterface * >(
179 3446 : &pProxy->vtables);
180 : }
181 :
182 5976 : CppInterfaceProxy * CppInterfaceProxy::castInterfaceToProxy(void * pInterface)
183 : {
184 : // pInterface == &pProxy->vtables (this emulated offsetof is not truly
185 : // portable):
186 5976 : char const * const base = reinterpret_cast< char const * >(16);
187 : std::ptrdiff_t const offset = reinterpret_cast< char const * >(
188 5976 : &reinterpret_cast< CppInterfaceProxy const * >(base)->vtables) - base;
189 : return reinterpret_cast< CppInterfaceProxy * >(
190 5976 : static_cast< char * >(pInterface) - offset);
191 : }
192 :
193 : } } }
194 :
195 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|