xref: /trunk/main/cppu/source/threadpool/current.cxx (revision 129fa3d1)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_cppu.hxx"
26 
27 #include "rtl/uuid.h"
28 #include "osl/thread.h"
29 #include "osl/mutex.hxx"
30 
31 #include "uno/environment.hxx"
32 #include "uno/mapping.hxx"
33 #include "uno/lbnames.h"
34 #include "typelib/typedescription.h"
35 
36 #include "current.hxx"
37 
38 
39 using namespace ::osl;
40 using namespace ::rtl;
41 using namespace ::cppu;
42 using namespace ::com::sun::star::uno;
43 
44 namespace cppu
45 {
46 
47 //--------------------------------------------------------------------------------------------------
48 class SAL_NO_VTABLE XInterface
49 {
50 public:
51     virtual void SAL_CALL slot_queryInterface() = 0;
52     virtual void SAL_CALL acquire() throw () = 0;
53     virtual void SAL_CALL release() throw () = 0;
54 };
55 //--------------------------------------------------------------------------------------------------
get_type_XCurrentContext()56 static typelib_InterfaceTypeDescription * get_type_XCurrentContext()
57 {
58     static typelib_InterfaceTypeDescription * s_type_XCurrentContext = 0;
59     if (0 == s_type_XCurrentContext)
60     {
61         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
62         if (0 == s_type_XCurrentContext)
63         {
64             OUString sTypeName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XCurrentContext") );
65             typelib_InterfaceTypeDescription * pTD = 0;
66             typelib_TypeDescriptionReference * pMembers[1] = { 0 };
67             OUString sMethodName0(
68                 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XCurrentContext::getValueByName") );
69             typelib_typedescriptionreference_new(
70                 &pMembers[0],
71                 typelib_TypeClass_INTERFACE_METHOD,
72                 sMethodName0.pData );
73             typelib_typedescription_newInterface(
74                 &pTD,
75                 sTypeName.pData, 0x00000000, 0x0000, 0x0000, 0x00000000, 0x00000000,
76                 * typelib_static_type_getByTypeClass( typelib_TypeClass_INTERFACE ),
77                 1,
78                 pMembers );
79 
80             typelib_typedescription_register( (typelib_TypeDescription**)&pTD );
81             typelib_typedescriptionreference_release( pMembers[0] );
82 
83             typelib_InterfaceMethodTypeDescription * pMethod = 0;
84             typelib_Parameter_Init aParameters[1];
85             OUString sParamName0( RTL_CONSTASCII_USTRINGPARAM("Name") );
86             OUString sParamType0( RTL_CONSTASCII_USTRINGPARAM("string") );
87             aParameters[0].pParamName = sParamName0.pData;
88             aParameters[0].eTypeClass = typelib_TypeClass_STRING;
89             aParameters[0].pTypeName = sParamType0.pData;
90             aParameters[0].bIn = sal_True;
91             aParameters[0].bOut = sal_False;
92             rtl_uString * pExceptions[1];
93             OUString sExceptionName0(
94                 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.RuntimeException") );
95             pExceptions[0] = sExceptionName0.pData;
96             OUString sReturnType0( RTL_CONSTASCII_USTRINGPARAM("any") );
97             typelib_typedescription_newInterfaceMethod(
98                 &pMethod,
99                 3, sal_False,
100                 sMethodName0.pData,
101                 typelib_TypeClass_ANY, sReturnType0.pData,
102                 1, aParameters, 1, pExceptions );
103             typelib_typedescription_register( (typelib_TypeDescription**)&pMethod );
104             typelib_typedescription_release( (typelib_TypeDescription*)pMethod );
105             // another static ref:
106             ++reinterpret_cast< typelib_TypeDescription * >( pTD )->
107                 nStaticRefCount;
108             s_type_XCurrentContext = pTD;
109         }
110     }
111     return s_type_XCurrentContext;
112 }
113 
114 //##################################################################################################
115 
116 //==================================================================================================
117 class ThreadKey
118 {
119 	sal_Bool	 _bInit;
120 	oslThreadKey _hThreadKey;
121 	oslThreadKeyCallbackFunction _pCallback;
122 
123 public:
124 	inline oslThreadKey getThreadKey() SAL_THROW( () );
125 
126 	inline ThreadKey( oslThreadKeyCallbackFunction pCallback ) SAL_THROW( () );
127 	inline ~ThreadKey() SAL_THROW( () );
128 };
129 //__________________________________________________________________________________________________
ThreadKey(oslThreadKeyCallbackFunction pCallback)130 inline ThreadKey::ThreadKey( oslThreadKeyCallbackFunction pCallback ) SAL_THROW( () )
131 	: _bInit( sal_False )
132 	, _pCallback( pCallback )
133 {
134 }
135 //__________________________________________________________________________________________________
~ThreadKey()136 inline ThreadKey::~ThreadKey() SAL_THROW( () )
137 {
138 	if (_bInit)
139 	{
140 		::osl_destroyThreadKey( _hThreadKey );
141 	}
142 }
143 //__________________________________________________________________________________________________
getThreadKey()144 inline oslThreadKey ThreadKey::getThreadKey() SAL_THROW( () )
145 {
146 	if (! _bInit)
147 	{
148 		MutexGuard aGuard( Mutex::getGlobalMutex() );
149 		if (! _bInit)
150 		{
151 			_hThreadKey = ::osl_createThreadKey( _pCallback );
152 			_bInit = sal_True;
153 		}
154 	}
155 	return _hThreadKey;
156 }
157 
158 //==================================================================================================
delete_IdContainer(void * p)159 extern "C" void SAL_CALL delete_IdContainer( void * p )
160 {
161 	if (p)
162 	{
163 		IdContainer * pId = reinterpret_cast< IdContainer * >( p );
164 		if (pId->pCurrentContext)
165 		{
166             (*pId->pCurrentContextEnv->releaseInterface)(
167                 pId->pCurrentContextEnv, pId->pCurrentContext );
168             (*((uno_Environment *)pId->pCurrentContextEnv)->release)(
169                 (uno_Environment *)pId->pCurrentContextEnv );
170 		}
171 		if (pId->bInit)
172 		{
173 			::rtl_byte_sequence_release( pId->pLocalThreadId );
174 			::rtl_byte_sequence_release( pId->pCurrentId );
175 		}
176 		delete pId;
177 	}
178 }
179 //==================================================================================================
getIdContainer()180 IdContainer * getIdContainer() SAL_THROW( () )
181 {
182 	static ThreadKey s_key( delete_IdContainer );
183 	oslThreadKey aKey = s_key.getThreadKey();
184 
185 	IdContainer * pId = reinterpret_cast< IdContainer * >( ::osl_getThreadKeyData( aKey ) );
186 	if (! pId)
187 	{
188 		pId = new IdContainer();
189 		pId->pCurrentContext = 0;
190         pId->pCurrentContextEnv = 0;
191 		pId->bInit = sal_False;
192 		::osl_setThreadKeyData( aKey, pId );
193 	}
194 	return pId;
195 }
196 
197 }
198 
199 //##################################################################################################
uno_setCurrentContext(void * pCurrentContext,rtl_uString * pEnvTypeName,void * pEnvContext)200 extern "C" sal_Bool SAL_CALL uno_setCurrentContext(
201 	void * pCurrentContext,
202 	rtl_uString * pEnvTypeName, void * pEnvContext )
203 	SAL_THROW_EXTERN_C()
204 {
205     IdContainer * pId = getIdContainer();
206     OSL_ASSERT( pId );
207 
208     // free old one
209     if (pId->pCurrentContext)
210     {
211         (*pId->pCurrentContextEnv->releaseInterface)(
212             pId->pCurrentContextEnv, pId->pCurrentContext );
213         (*((uno_Environment *)pId->pCurrentContextEnv)->release)(
214             (uno_Environment *)pId->pCurrentContextEnv );
215         pId->pCurrentContextEnv = 0;
216 
217         pId->pCurrentContext = 0;
218     }
219 
220     if (pCurrentContext)
221     {
222         uno_Environment * pEnv = 0;
223         ::uno_getEnvironment( &pEnv, pEnvTypeName, pEnvContext );
224         OSL_ASSERT( pEnv && pEnv->pExtEnv );
225         if (pEnv)
226         {
227             if (pEnv->pExtEnv)
228             {
229                 pId->pCurrentContextEnv = pEnv->pExtEnv;
230                 (*pId->pCurrentContextEnv->acquireInterface)(
231                     pId->pCurrentContextEnv, pCurrentContext );
232                 pId->pCurrentContext = pCurrentContext;
233             }
234             else
235             {
236                 (*pEnv->release)( pEnv );
237                 return sal_False;
238             }
239         }
240         else
241         {
242             return sal_False;
243         }
244     }
245     return sal_True;
246 }
247 //##################################################################################################
uno_getCurrentContext(void ** ppCurrentContext,rtl_uString * pEnvTypeName,void * pEnvContext)248 extern "C" sal_Bool SAL_CALL uno_getCurrentContext(
249 	void ** ppCurrentContext, rtl_uString * pEnvTypeName, void * pEnvContext )
250 	SAL_THROW_EXTERN_C()
251 {
252     IdContainer * pId = getIdContainer();
253     OSL_ASSERT( pId );
254 
255     Environment target_env;
256 
257     // release inout parameter
258     if (*ppCurrentContext)
259     {
260         target_env = Environment(rtl::OUString(pEnvTypeName), pEnvContext);
261         OSL_ASSERT( target_env.is() );
262         if (! target_env.is())
263             return sal_False;
264         uno_ExtEnvironment * pEnv = target_env.get()->pExtEnv;
265         OSL_ASSERT( 0 != pEnv );
266         if (0 == pEnv)
267             return sal_False;
268         (*pEnv->releaseInterface)( pEnv, *ppCurrentContext );
269 
270         *ppCurrentContext = 0;
271     }
272 
273     // case: null-ref
274     if (0 == pId->pCurrentContext)
275         return sal_True;
276 
277     if (! target_env.is())
278     {
279         target_env = Environment(rtl::OUString(pEnvTypeName), pEnvContext);
280         OSL_ASSERT( target_env.is() );
281         if (! target_env.is())
282             return sal_False;
283     }
284 
285     Mapping mapping((uno_Environment *) pId->pCurrentContextEnv, target_env.get());
286     OSL_ASSERT( mapping.is() );
287     if (! mapping.is())
288         return sal_False;
289 
290     mapping.mapInterface(ppCurrentContext, pId->pCurrentContext, ::cppu::get_type_XCurrentContext() );
291 
292     return sal_True;
293 }
294