Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / cppu / source / threadpool / current.cxx
blob7dbfc9050488c71a72be75eca9c1ed9cf44538f3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
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>
22 #include <rtl/byteseq.h>
23 #include <osl/thread.h>
24 #include <osl/mutex.hxx>
26 #include <uno/current_context.h>
27 #include <uno/environment.hxx>
28 #include <uno/mapping.hxx>
29 #include <typelib/typedescription.h>
31 #include "current.hxx"
34 using namespace ::osl;
35 using namespace ::rtl;
36 using namespace ::cppu;
37 using namespace ::com::sun::star::uno;
39 namespace cppu
42 static typelib_InterfaceTypeDescription * get_type_XCurrentContext()
44 static typelib_InterfaceTypeDescription* s_type_XCurrentContext = []() {
45 OUString sTypeName("com.sun.star.uno.XCurrentContext");
46 typelib_InterfaceTypeDescription* pTD = nullptr;
47 typelib_TypeDescriptionReference* pMembers[1] = { nullptr };
48 OUString sMethodName0("com.sun.star.uno.XCurrentContext::getValueByName");
49 typelib_typedescriptionreference_new(&pMembers[0], typelib_TypeClass_INTERFACE_METHOD,
50 sMethodName0.pData);
51 typelib_typedescription_newInterface(
52 &pTD, sTypeName.pData, 0, 0, 0, 0, 0,
53 *typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE), 1, pMembers);
55 typelib_typedescription_register(reinterpret_cast<typelib_TypeDescription**>(&pTD));
56 typelib_typedescriptionreference_release(pMembers[0]);
58 typelib_InterfaceMethodTypeDescription* pMethod = nullptr;
59 typelib_Parameter_Init aParameters[1];
60 OUString sParamName0("Name");
61 OUString sParamType0("string");
62 aParameters[0].pParamName = sParamName0.pData;
63 aParameters[0].eTypeClass = typelib_TypeClass_STRING;
64 aParameters[0].pTypeName = sParamType0.pData;
65 aParameters[0].bIn = true;
66 aParameters[0].bOut = false;
67 rtl_uString* pExceptions[1];
68 OUString sExceptionName0("com.sun.star.uno.RuntimeException");
69 pExceptions[0] = sExceptionName0.pData;
70 OUString sReturnType0("any");
71 typelib_typedescription_newInterfaceMethod(&pMethod, 3, false, sMethodName0.pData,
72 typelib_TypeClass_ANY, sReturnType0.pData, 1,
73 aParameters, 1, pExceptions);
74 typelib_typedescription_register(reinterpret_cast<typelib_TypeDescription**>(&pMethod));
75 typelib_typedescription_release(&pMethod->aBase.aBase);
76 // another static ref:
77 ++reinterpret_cast<typelib_TypeDescription*>(pTD)->nStaticRefCount;
78 return pTD;
79 }();
81 return s_type_XCurrentContext;
84 namespace {
86 class ThreadKey
88 bool _bInit;
89 oslThreadKey _hThreadKey;
90 oslThreadKeyCallbackFunction _pCallback;
92 public:
93 oslThreadKey getThreadKey()
95 if (! _bInit)
97 MutexGuard aGuard( Mutex::getGlobalMutex() );
98 if (! _bInit)
100 _hThreadKey = ::osl_createThreadKey( _pCallback );
101 _bInit = true;
104 return _hThreadKey;
107 explicit ThreadKey( oslThreadKeyCallbackFunction pCallback )
108 : _bInit(false)
109 , _hThreadKey(nullptr)
110 , _pCallback(pCallback)
114 ~ThreadKey()
116 if (_bInit)
118 ::osl_destroyThreadKey( _hThreadKey );
125 extern "C" {
127 static void delete_IdContainer( void * p )
129 if (!p)
130 return;
132 IdContainer * pId = static_cast< IdContainer * >( p );
133 if (pId->pCurrentContext)
135 (*pId->pCurrentContextEnv->releaseInterface)(
136 pId->pCurrentContextEnv, pId->pCurrentContext );
137 (*pId->pCurrentContextEnv->aBase.release)(
138 &pId->pCurrentContextEnv->aBase );
140 if (pId->bInit)
142 ::rtl_byte_sequence_release( pId->pLocalThreadId );
143 ::rtl_byte_sequence_release( pId->pCurrentId );
145 delete pId;
150 IdContainer * getIdContainer()
152 static ThreadKey s_key( delete_IdContainer );
153 oslThreadKey aKey = s_key.getThreadKey();
155 IdContainer * pId = static_cast< IdContainer * >( ::osl_getThreadKeyData( aKey ) );
156 if (! pId)
158 pId = new IdContainer;
159 pId->pCurrentContext = nullptr;
160 pId->pCurrentContextEnv = nullptr;
161 pId->bInit = false;
162 ::osl_setThreadKeyData( aKey, pId );
164 return pId;
170 extern "C" sal_Bool SAL_CALL uno_setCurrentContext(
171 void * pCurrentContext,
172 rtl_uString * pEnvTypeName, void * pEnvContext )
173 SAL_THROW_EXTERN_C()
175 IdContainer * pId = getIdContainer();
176 OSL_ASSERT( pId );
178 // free old one
179 if (pId->pCurrentContext)
181 (*pId->pCurrentContextEnv->releaseInterface)(
182 pId->pCurrentContextEnv, pId->pCurrentContext );
183 (*pId->pCurrentContextEnv->aBase.release)(
184 &pId->pCurrentContextEnv->aBase );
185 pId->pCurrentContextEnv = nullptr;
187 pId->pCurrentContext = nullptr;
190 if (pCurrentContext)
192 uno_Environment * pEnv = nullptr;
193 ::uno_getEnvironment( &pEnv, pEnvTypeName, pEnvContext );
194 OSL_ASSERT( pEnv && pEnv->pExtEnv );
195 if (pEnv)
197 if (pEnv->pExtEnv)
199 pId->pCurrentContextEnv = pEnv->pExtEnv;
200 (*pId->pCurrentContextEnv->acquireInterface)(
201 pId->pCurrentContextEnv, pCurrentContext );
202 pId->pCurrentContext = pCurrentContext;
204 else
206 (*pEnv->release)( pEnv );
207 return false;
210 else
212 return false;
215 return true;
218 extern "C" sal_Bool SAL_CALL uno_getCurrentContext(
219 void ** ppCurrentContext, rtl_uString * pEnvTypeName, void * pEnvContext )
220 SAL_THROW_EXTERN_C()
222 IdContainer * pId = getIdContainer();
223 OSL_ASSERT( pId );
225 Environment target_env;
227 // release inout parameter
228 if (*ppCurrentContext)
230 target_env = Environment(OUString(pEnvTypeName), pEnvContext);
231 OSL_ASSERT( target_env.is() );
232 if (! target_env.is())
233 return false;
234 uno_ExtEnvironment * pEnv = target_env.get()->pExtEnv;
235 OSL_ASSERT( nullptr != pEnv );
236 if (nullptr == pEnv)
237 return false;
238 (*pEnv->releaseInterface)( pEnv, *ppCurrentContext );
240 *ppCurrentContext = nullptr;
243 // case: null-ref
244 if (nullptr == pId->pCurrentContext)
245 return true;
247 if (! target_env.is())
249 target_env = Environment(OUString(pEnvTypeName), pEnvContext);
250 OSL_ASSERT( target_env.is() );
251 if (! target_env.is())
252 return false;
255 Mapping mapping(&pId->pCurrentContextEnv->aBase, target_env.get());
256 OSL_ASSERT( mapping.is() );
257 if (! mapping.is())
258 return false;
260 mapping.mapInterface(ppCurrentContext, pId->pCurrentContext, ::cppu::get_type_XCurrentContext() );
262 return true;
265 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */