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