xref: /trunk/main/cppu/source/threadpool/current.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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