cid#1607171 Data race condition
[LibreOffice.git] / cppu / source / threadpool / current.cxx
blobefb66e3166bad358d0d785dc40d2385e50fb5fef
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/mutex.hxx>
25 #include <uno/current_context.h>
26 #include <uno/environment.hxx>
27 #include <uno/mapping.hxx>
28 #include <typelib/typedescription.h>
30 #include "current.hxx"
33 using namespace ::rtl;
34 using namespace ::cppu;
35 using namespace ::com::sun::star::uno;
37 namespace cppu
40 static typelib_InterfaceTypeDescription * impl_get_type_XCurrentContext()
42 OUString sTypeName(u"com.sun.star.uno.XCurrentContext"_ustr);
43 typelib_InterfaceTypeDescription* pTD = nullptr;
44 typelib_TypeDescriptionReference* pMembers[1] = { nullptr };
45 OUString sMethodName0(u"com.sun.star.uno.XCurrentContext::getValueByName"_ustr);
46 typelib_typedescriptionreference_new(&pMembers[0], typelib_TypeClass_INTERFACE_METHOD,
47 sMethodName0.pData);
48 typelib_typedescription_newInterface(
49 &pTD, sTypeName.pData, 0, 0, 0, 0, 0,
50 *typelib_static_type_getByTypeClass(typelib_TypeClass_INTERFACE), 1, pMembers);
52 typelib_typedescription_register(reinterpret_cast<typelib_TypeDescription**>(&pTD));
53 typelib_typedescriptionreference_release(pMembers[0]);
55 typelib_InterfaceMethodTypeDescription* pMethod = nullptr;
56 typelib_Parameter_Init aParameters[1];
57 OUString sParamName0(u"Name"_ustr);
58 OUString sParamType0(u"string"_ustr);
59 aParameters[0].pParamName = sParamName0.pData;
60 aParameters[0].eTypeClass = typelib_TypeClass_STRING;
61 aParameters[0].pTypeName = sParamType0.pData;
62 aParameters[0].bIn = true;
63 aParameters[0].bOut = false;
64 rtl_uString* pExceptions[1];
65 OUString sExceptionName0(u"com.sun.star.uno.RuntimeException"_ustr);
66 pExceptions[0] = sExceptionName0.pData;
67 OUString sReturnType0(u"any"_ustr);
68 typelib_typedescription_newInterfaceMethod(&pMethod, 3, false, sMethodName0.pData,
69 typelib_TypeClass_ANY, sReturnType0.pData, 1,
70 aParameters, 1, pExceptions);
71 typelib_typedescription_register(reinterpret_cast<typelib_TypeDescription**>(&pMethod));
72 typelib_typedescription_release(&pMethod->aBase.aBase);
73 // another static ref:
74 ++reinterpret_cast<typelib_TypeDescription*>(pTD)->nStaticRefCount;
75 return pTD;
78 static typelib_InterfaceTypeDescription * get_type_XCurrentContext()
80 static typelib_InterfaceTypeDescription* s_type_XCurrentContext = impl_get_type_XCurrentContext();
81 return s_type_XCurrentContext;
84 IdContainer::IdContainer()
85 : pCurrentContext(nullptr)
86 , pCurrentContextEnv(nullptr)
87 , pLocalThreadId(nullptr)
88 , pCurrentId(nullptr)
89 , nRefCountOfCurrentId(0)
90 , bInit(false)
94 IdContainer::~IdContainer()
96 if (pCurrentContext)
98 (*pCurrentContextEnv->releaseInterface)(
99 pCurrentContextEnv, pCurrentContext );
100 (*pCurrentContextEnv->aBase.release)(
101 &pCurrentContextEnv->aBase );
103 if (bInit)
105 ::rtl_byte_sequence_release( pLocalThreadId );
106 ::rtl_byte_sequence_release( pCurrentId );
110 IdContainer& getIdContainer()
112 static thread_local IdContainer aId;
113 return aId;
118 extern "C" sal_Bool SAL_CALL uno_setCurrentContext(
119 void * pCurrentContext,
120 rtl_uString * pEnvTypeName, void * pEnvContext ) noexcept
122 IdContainer& id = getIdContainer();
124 // free old one
125 if (id.pCurrentContext)
127 (*id.pCurrentContextEnv->releaseInterface)(
128 id.pCurrentContextEnv, id.pCurrentContext );
129 (*id.pCurrentContextEnv->aBase.release)(
130 &id.pCurrentContextEnv->aBase );
131 id.pCurrentContextEnv = nullptr;
133 id.pCurrentContext = nullptr;
136 if (!pCurrentContext)
137 return true;
139 uno_Environment * pEnv = nullptr;
140 ::uno_getEnvironment( &pEnv, pEnvTypeName, pEnvContext );
141 OSL_ASSERT( pEnv && pEnv->pExtEnv );
142 if (pEnv)
144 if (pEnv->pExtEnv)
146 id.pCurrentContextEnv = pEnv->pExtEnv;
147 (*id.pCurrentContextEnv->acquireInterface)(
148 id.pCurrentContextEnv, pCurrentContext );
149 id.pCurrentContext = pCurrentContext;
151 else
153 (*pEnv->release)( pEnv );
154 return false;
157 else
159 return false;
161 return true;
164 extern "C" sal_Bool SAL_CALL uno_getCurrentContext(
165 void ** ppCurrentContext, rtl_uString * pEnvTypeName, void * pEnvContext ) noexcept
167 IdContainer& id = getIdContainer();
169 Environment target_env;
171 // release inout parameter
172 if (*ppCurrentContext)
174 target_env = Environment(OUString(pEnvTypeName), pEnvContext);
175 OSL_ASSERT( target_env.is() );
176 if (! target_env.is())
177 return false;
178 uno_ExtEnvironment * pEnv = target_env.get()->pExtEnv;
179 OSL_ASSERT( nullptr != pEnv );
180 if (nullptr == pEnv)
181 return false;
182 (*pEnv->releaseInterface)( pEnv, *ppCurrentContext );
184 *ppCurrentContext = nullptr;
187 // case: null-ref
188 if (nullptr == id.pCurrentContext)
189 return true;
191 if (! target_env.is())
193 target_env = Environment(OUString(pEnvTypeName), pEnvContext);
194 OSL_ASSERT( target_env.is() );
195 if (! target_env.is())
196 return false;
199 Mapping mapping(&id.pCurrentContextEnv->aBase, target_env.get());
200 OSL_ASSERT( mapping.is() );
201 if (! mapping.is())
202 return false;
204 mapping.mapInterface(ppCurrentContext, id.pCurrentContext, ::cppu::get_type_XCurrentContext());
206 return true;
209 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */