1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include "IdentityMapping.hxx"
23 #include <boost/unordered_map.hpp>
27 #include "rtl/unload.h"
28 #include "rtl/ustring.hxx"
29 #include "rtl/ustrbuf.hxx"
30 #include "osl/module.h"
31 #include "osl/diagnose.h"
32 #include "osl/mutex.hxx"
33 #include "osl/interlck.h"
35 #include "uno/dispatcher.h"
36 #include "uno/mapping.h"
37 #include "uno/lbnames.h"
38 #include "uno/environment.hxx"
40 #include "typelib/typedescription.h"
42 #include "cppu/EnvDcp.hxx"
43 #include "cascade_mapping.hxx"
44 #include "IdentityMapping.hxx"
45 #include "loadmodule.hxx"
49 using namespace com::sun::star::uno
;
50 using ::rtl::OUString
;
51 using ::rtl::OUStringBuffer
;
52 using ::rtl::OUStringToOString
;
60 uno_Mapping
* _pMapping
;
63 inline explicit Mapping( uno_Mapping
* pMapping
= 0 ) SAL_THROW(());
64 inline Mapping( const Mapping
& rMapping
) SAL_THROW(());
65 inline ~Mapping() SAL_THROW(());
66 inline Mapping
& SAL_CALL
operator = ( uno_Mapping
* pMapping
) SAL_THROW(());
67 inline Mapping
& SAL_CALL
operator = ( const Mapping
& rMapping
) SAL_THROW(())
68 { return operator = ( rMapping
._pMapping
); }
69 inline uno_Mapping
* SAL_CALL
get() const SAL_THROW(())
71 inline sal_Bool SAL_CALL
is() const SAL_THROW(())
72 { return (_pMapping
!= 0); }
74 //__________________________________________________________________________________________________
75 inline Mapping::Mapping( uno_Mapping
* pMapping
) SAL_THROW(())
76 : _pMapping( pMapping
)
79 (*_pMapping
->acquire
)( _pMapping
);
81 //__________________________________________________________________________________________________
82 inline Mapping::Mapping( const Mapping
& rMapping
) SAL_THROW(())
83 : _pMapping( rMapping
._pMapping
)
86 (*_pMapping
->acquire
)( _pMapping
);
88 //__________________________________________________________________________________________________
89 inline Mapping::~Mapping() SAL_THROW(())
92 (*_pMapping
->release
)( _pMapping
);
94 //__________________________________________________________________________________________________
95 inline Mapping
& Mapping::operator = ( uno_Mapping
* pMapping
) SAL_THROW(())
98 (*pMapping
->acquire
)( pMapping
);
100 (*_pMapping
->release
)( _pMapping
);
101 _pMapping
= pMapping
;
105 //==================================================================================================
109 uno_Mapping
* pMapping
;
110 uno_freeMappingFunc freeMapping
;
111 OUString aMappingName
;
114 uno_Mapping
* pMapping_
, uno_freeMappingFunc freeMapping_
,
115 const OUString
& rMappingName_
)
118 , pMapping( pMapping_
)
119 , freeMapping( freeMapping_
)
120 , aMappingName( rMappingName_
)
123 //--------------------------------------------------------------------------------------------------
124 struct FctOUStringHash
: public std::unary_function
< const OUString
&, size_t >
126 size_t operator()( const OUString
& rKey
) const SAL_THROW(())
127 { return (size_t)rKey
.hashCode(); }
129 //--------------------------------------------------------------------------------------------------
130 struct FctPtrHash
: public std::unary_function
< uno_Mapping
*, size_t >
132 size_t operator()( uno_Mapping
* pKey
) const SAL_THROW(())
133 { return (size_t)pKey
; }
136 typedef boost::unordered_map
<
137 OUString
, MappingEntry
*, FctOUStringHash
, equal_to
< OUString
> > t_OUString2Entry
;
138 typedef boost::unordered_map
<
139 uno_Mapping
*, MappingEntry
*, FctPtrHash
, equal_to
< uno_Mapping
* > > t_Mapping2Entry
;
141 typedef set
< uno_getMappingFunc
> t_CallbackSet
;
142 typedef set
< OUString
> t_OUStringSet
;
144 //==================================================================================================
147 Mutex aMappingsMutex
;
148 t_OUString2Entry aName2Entry
;
149 t_Mapping2Entry aMapping2Entry
;
151 Mutex aCallbacksMutex
;
152 t_CallbackSet aCallbacks
;
154 Mutex aNegativeLibsMutex
;
155 t_OUStringSet aNegativeLibs
;
157 //--------------------------------------------------------------------------------------------------
158 static MappingsData
& getMappingsData() SAL_THROW(())
160 static MappingsData
* s_p
= 0;
163 MutexGuard
aGuard( Mutex::getGlobalMutex() );
166 //TODO This memory is leaked; see #i63473# for when this should be
168 s_p
= new MappingsData
;
175 * This class mediates two different mapping via uno, e.g. form any language to uno,
176 * then from uno to any other language.
178 struct uno_Mediate_Mapping
: public uno_Mapping
188 OUString aAddPurpose
;
191 const Environment
& rFrom_
, const Environment
& rTo_
,
192 const Mapping
& rFrom2Uno_
, const Mapping
& rUno2To_
,
193 const OUString
& rAddPurpose
)
198 //--------------------------------------------------------------------------------------------------
199 static void SAL_CALL
mediate_free( uno_Mapping
* pMapping
)
202 delete static_cast< uno_Mediate_Mapping
* >( pMapping
);
204 //--------------------------------------------------------------------------------------------------
205 static void SAL_CALL
mediate_acquire( uno_Mapping
* pMapping
)
208 if (1 == ::osl_atomic_increment(
209 & static_cast< uno_Mediate_Mapping
* >( pMapping
)->nRef
))
212 &pMapping
, mediate_free
,
213 static_cast< uno_Mediate_Mapping
* >( pMapping
)->aFrom
.get(),
214 static_cast< uno_Mediate_Mapping
* >( pMapping
)->aTo
.get(),
215 static_cast< uno_Mediate_Mapping
* >( pMapping
)->aAddPurpose
.pData
);
218 //--------------------------------------------------------------------------------------------------
219 static void SAL_CALL
mediate_release( uno_Mapping
* pMapping
)
222 if (! ::osl_atomic_decrement(
223 & static_cast< uno_Mediate_Mapping
* >( pMapping
)->nRef
))
225 uno_revokeMapping( pMapping
);
228 //--------------------------------------------------------------------------------------------------
229 static void SAL_CALL
mediate_mapInterface(
230 uno_Mapping
* pMapping
,
231 void ** ppOut
, void * pInterface
,
232 typelib_InterfaceTypeDescription
* pInterfaceTypeDescr
)
235 OSL_ENSURE( pMapping
&& ppOut
, "### null ptr!" );
236 if (pMapping
&& ppOut
)
238 uno_Mediate_Mapping
* that
= static_cast< uno_Mediate_Mapping
* >( pMapping
);
239 uno_Mapping
* pFrom2Uno
= that
->aFrom2Uno
.get();
241 uno_Interface
* pUnoI
= 0;
242 (*pFrom2Uno
->mapInterface
)( pFrom2Uno
, (void **) &pUnoI
, pInterface
, pInterfaceTypeDescr
);
245 void * pOut
= *ppOut
;
248 uno_ExtEnvironment
* pTo
= that
->aTo
.get()->pExtEnv
;
249 OSL_ENSURE( 0 != pTo
, "### cannot release out interface: leaking!" );
251 (*pTo
->releaseInterface
)( pTo
, pOut
);
252 *ppOut
= 0; // set to 0 anyway, because mapping was not successfull!
257 uno_Mapping
* pUno2To
= that
->aUno2To
.get();
258 (*pUno2To
->mapInterface
)( pUno2To
, ppOut
, pUnoI
, pInterfaceTypeDescr
);
259 (*pUnoI
->release
)( pUnoI
);
264 //__________________________________________________________________________________________________
265 uno_Mediate_Mapping::uno_Mediate_Mapping(
266 const Environment
& rFrom_
, const Environment
& rTo_
,
267 const Mapping
& rFrom2Uno_
, const Mapping
& rUno2To_
,
268 const OUString
& rAddPurpose_
)
273 , aFrom2Uno( rFrom2Uno_
)
274 , aUno2To( rUno2To_
)
275 , aAddPurpose( rAddPurpose_
)
277 uno_Mapping::acquire
= mediate_acquire
;
278 uno_Mapping::release
= mediate_release
;
279 uno_Mapping::mapInterface
= mediate_mapInterface
;
282 //==================================================================================================
283 static inline OUString
getMappingName(
284 const Environment
& rFrom
, const Environment
& rTo
, const OUString
& rAddPurpose
)
287 OUStringBuffer
aKey( 64 );
288 aKey
.append( rAddPurpose
);
289 aKey
.append( (sal_Unicode
)';' );
290 aKey
.append( rFrom
.getTypeName() );
291 aKey
.append( (sal_Unicode
)'[' );
292 aKey
.append( reinterpret_cast< sal_IntPtr
>(rFrom
.get()), 16 );
293 aKey
.appendAscii( RTL_CONSTASCII_STRINGPARAM("];") );
294 aKey
.append( rTo
.getTypeName() );
295 aKey
.append( (sal_Unicode
)'[' );
296 aKey
.append( reinterpret_cast< sal_IntPtr
>(rTo
.get()), 16 );
297 aKey
.append( (sal_Unicode
)']' );
298 return aKey
.makeStringAndClear();
300 //==================================================================================================
301 static inline OUString
getBridgeName(
302 const Environment
& rFrom
, const Environment
& rTo
, const OUString
& rAddPurpose
)
305 OUStringBuffer
aBridgeName( 16 );
306 if (!rAddPurpose
.isEmpty())
308 aBridgeName
.append( rAddPurpose
);
309 aBridgeName
.append( (sal_Unicode
)'_' );
311 aBridgeName
.append( EnvDcp::getTypeName(rFrom
.getTypeName()) );
312 aBridgeName
.append( (sal_Unicode
)'_' );
313 aBridgeName
.append( EnvDcp::getTypeName(rTo
.getTypeName()) );
314 return aBridgeName
.makeStringAndClear();
316 //==================================================================================================
317 static inline void setNegativeBridge( const OUString
& rBridgeName
)
320 MappingsData
& rData
= getMappingsData();
321 MutexGuard
aGuard( rData
.aNegativeLibsMutex
);
322 rData
.aNegativeLibs
.insert( rBridgeName
);
325 #ifdef DISABLE_DYNLOADING
327 static uno_ext_getMappingFunc
selectMapFunc( const OUString
& rBridgeName
)
330 if (rBridgeName
.equalsAscii( CPPU_CURRENT_LANGUAGE_BINDING_NAME
"_uno" ))
331 return CPPU_ENV_uno_ext_getMapping
;
333 if (rBridgeName
.equalsAscii( "java" "_uno" ))
334 return java_uno_ext_getMapping
;
338 // I don't think the affine or log bridges will be needed on any
339 // DISABLE_DYNLOADING platform (iOS at least, possibly Android), but if
340 // somebody wants to experiment, need to find out then whether these are
342 if (rBridgeName
.equalsAscii( "affine_uno_uno" ))
343 return affine_uno_uno_ext_getMapping
;
344 if (rBridgeName
.equalsAscii( "log_uno_uno" ))
345 return log_uno_uno_ext_getMapping
;
352 static inline oslModule
loadModule( const OUString
& rBridgeName
)
357 MappingsData
& rData
= getMappingsData();
358 MutexGuard
aGuard( rData
.aNegativeLibsMutex
);
359 const t_OUStringSet::const_iterator
iFind( rData
.aNegativeLibs
.find( rBridgeName
) );
360 bNeg
= (iFind
!= rData
.aNegativeLibs
.end());
365 oslModule hModule
= cppu::detail::loadModule( rBridgeName
);
370 setNegativeBridge( rBridgeName
); // no load again
377 //==================================================================================================
378 static Mapping
loadExternalMapping(
379 const Environment
& rFrom
, const Environment
& rTo
, const OUString
& rAddPurpose
)
382 OSL_ASSERT( rFrom
.is() && rTo
.is() );
383 if (rFrom
.is() && rTo
.is())
385 #ifdef DISABLE_DYNLOADING
387 uno_ext_getMappingFunc fpGetMapFunc
= 0;
389 if (EnvDcp::getTypeName(rFrom
.getTypeName()).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(UNO_LB_UNO
) ))
391 aName
= getBridgeName( rTo
, rFrom
, rAddPurpose
);
392 fpGetMapFunc
= selectMapFunc( aName
);
396 aName
= getBridgeName( rFrom
, rTo
, rAddPurpose
);
397 fpGetMapFunc
= selectMapFunc( aName
);
401 aName
= getBridgeName( rTo
, rFrom
, rAddPurpose
);
402 fpGetMapFunc
= selectMapFunc( aName
);
407 #if OSL_DEBUG_LEVEL > 1
408 OSL_TRACE( "Could not find mapfunc for %s", OUStringToOString( aName
, RTL_TEXTENCODING_ASCII_US
).getStr());
416 (*fpGetMapFunc
)( (uno_Mapping
**)&aExt
, rFrom
.get(), rTo
.get() );
417 OSL_ASSERT( aExt
.is() );
423 oslModule hModule
= 0;
426 if ( EnvDcp::getTypeName(rFrom
.getTypeName()) == UNO_LB_UNO
)
427 hModule
= loadModule( aName
= getBridgeName( rTo
, rFrom
, rAddPurpose
) );
429 hModule
= loadModule( aName
= getBridgeName( rFrom
, rTo
, rAddPurpose
) );
431 hModule
= loadModule( aName
= getBridgeName( rTo
, rFrom
, rAddPurpose
) );
435 OUString
aSymbolName( RTL_CONSTASCII_USTRINGPARAM(UNO_EXT_GETMAPPING
) );
436 uno_ext_getMappingFunc fpGetMapFunc
=
437 (uno_ext_getMappingFunc
)::osl_getFunctionSymbol(
438 hModule
, aSymbolName
.pData
);
443 (*fpGetMapFunc
)( (uno_Mapping
**)&aExt
, rFrom
.get(), rTo
.get() );
444 OSL_ASSERT( aExt
.is() );
447 ::rtl_registerModuleForUnloading( hModule
);
451 ::osl_unloadModule( hModule
);
452 setNegativeBridge( aName
);
459 //==================================================================================================
460 static Mapping
getDirectMapping(
461 const Environment
& rFrom
, const Environment
& rTo
, const OUString
& rAddPurpose
= OUString() )
464 OSL_ASSERT( rFrom
.is() && rTo
.is() );
465 if (rFrom
.is() && rTo
.is())
467 MappingsData
& rData
= getMappingsData();
468 ClearableMutexGuard
aGuard( rData
.aMappingsMutex
);
470 // try to find registered mapping
471 const t_OUString2Entry::const_iterator
iFind( rData
.aName2Entry
.find(
472 getMappingName( rFrom
, rTo
, rAddPurpose
) ) );
474 if (iFind
== rData
.aName2Entry
.end())
477 return loadExternalMapping( rFrom
, rTo
, rAddPurpose
);
481 return Mapping( (*iFind
).second
->pMapping
);
487 //--------------------------------------------------------------------------------------------------
488 static inline Mapping
createMediateMapping(
489 const Environment
& rFrom
, const Environment
& rTo
,
490 const Mapping
& rFrom2Uno
, const Mapping
& rUno2To
,
491 const OUString
& rAddPurpose
)
494 uno_Mapping
* pRet
= new uno_Mediate_Mapping(
495 rFrom
, rTo
, rFrom2Uno
, rUno2To
, rAddPurpose
); // ref count initially 1
497 &pRet
, mediate_free
, rFrom
.get(), rTo
.get(), rAddPurpose
.pData
);
498 Mapping
aRet( pRet
);
499 (*pRet
->release
)( pRet
);
502 //==================================================================================================
503 static Mapping
getMediateMapping(
504 const Environment
& rFrom
, const Environment
& rTo
, const OUString
& rAddPurpose
)
510 // backwards: from dest to source of mapping chain
513 OUString
aUnoEnvTypeName( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO
) );
514 if (rTo
.getTypeName() == aUnoEnvTypeName
) // to is uno
517 // no Uno2To mapping necessary
521 // get registered uno env
522 ::uno_getEnvironment( (uno_Environment
**)&aUno
, aUnoEnvTypeName
.pData
, 0 );
524 aUno2To
= getDirectMapping( aUno
, rTo
);
531 if (!rAddPurpose
.isEmpty()) // insert purpose mapping between new ano_uno <-> uno
533 // create anonymous uno env
535 ::uno_createEnvironment( (uno_Environment
**)&aAnUno
, aUnoEnvTypeName
.pData
, 0 );
537 Mapping
aAnUno2Uno( getDirectMapping( aAnUno
, aUno
, rAddPurpose
) );
538 if (! aAnUno2Uno
.is())
541 if (aUno2To
.is()) // to is not uno
543 // create another purposed mediate mapping
544 aUno2To
= createMediateMapping( aAnUno
, rTo
, aAnUno2Uno
, aUno2To
, rAddPurpose
);
545 // : ano_uno <-> uno <-> to
549 aUno2To
= aAnUno2Uno
;
550 // : ano_uno <-> to (i.e., uno)
555 Mapping
aFrom2Uno( getDirectMapping( rFrom
, aUno
) );
556 if (aFrom2Uno
.is() && aUno2To
.is())
558 return createMediateMapping( rFrom
, rTo
, aFrom2Uno
, aUno2To
, rAddPurpose
);
559 // : from <-> some uno ...
566 using namespace ::cppu
;
570 //##################################################################################################
571 void SAL_CALL
uno_getMapping(
572 uno_Mapping
** ppMapping
, uno_Environment
* pFrom
, uno_Environment
* pTo
,
573 rtl_uString
* pAddPurpose
)
576 OSL_ENSURE( ppMapping
&& pFrom
&& pTo
, "### null ptr!" );
579 (*(*ppMapping
)->release
)( *ppMapping
);
584 Environment
aFrom( pFrom
), aTo( pTo
);
586 OUString aAddPurpose
;
588 aAddPurpose
= pAddPurpose
;
590 MappingsData
& rData
= getMappingsData();
592 // try registered mapping
594 MutexGuard
aGuard( rData
.aMappingsMutex
);
595 const t_OUString2Entry::const_iterator
iFind( rData
.aName2Entry
.find(
596 getMappingName( aFrom
, aTo
, aAddPurpose
) ) );
597 if (iFind
!= rData
.aName2Entry
.end())
598 aRet
= (*iFind
).second
->pMapping
;
601 // See if an identity mapping does fit.
602 if (!aRet
.is() && pFrom
== pTo
&& aAddPurpose
.isEmpty())
603 aRet
= createIdentityMapping(pFrom
);
607 getCascadeMapping(ppMapping
, pFrom
, pTo
, pAddPurpose
);
613 if (! aRet
.is()) // try callback chain
615 MutexGuard
aGuard( rData
.aCallbacksMutex
);
616 for ( t_CallbackSet::const_iterator
iPos( rData
.aCallbacks
.begin() );
617 iPos
!= rData
.aCallbacks
.end(); ++iPos
)
619 (**iPos
)( ppMapping
, pFrom
, pTo
, aAddPurpose
.pData
);
627 aRet
= loadExternalMapping( aFrom
, aTo
, aAddPurpose
); // direct try
629 aRet
= getMediateMapping( aFrom
, aTo
, aAddPurpose
); // try via uno
634 (*aRet
.get()->acquire
)( aRet
.get() );
635 *ppMapping
= aRet
.get();
638 //##################################################################################################
639 void SAL_CALL
uno_getMappingByName(
640 uno_Mapping
** ppMapping
, rtl_uString
* pFrom
, rtl_uString
* pTo
,
641 rtl_uString
* pAddPurpose
)
644 OSL_ENSURE( ppMapping
&& pFrom
&& pTo
, "### null ptr!" );
647 (*(*ppMapping
)->release
)( *ppMapping
);
651 uno_Environment
* pEFrom
= 0;
652 uno_getEnvironment( &pEFrom
, pFrom
, 0 );
653 OSL_ENSURE( pEFrom
, "### cannot get source environment!" );
656 uno_Environment
* pETo
= 0;
657 uno_getEnvironment( &pETo
, pTo
, 0 );
658 OSL_ENSURE( pETo
, "### cannot get target environment!" );
661 ::uno_getMapping( ppMapping
, pEFrom
, pETo
, pAddPurpose
);
662 (*pETo
->release
)( pETo
);
664 (*pEFrom
->release
)( pEFrom
);
668 //##################################################################################################
669 CPPU_DLLPUBLIC
void SAL_CALL
uno_registerMapping(
670 uno_Mapping
** ppMapping
, uno_freeMappingFunc freeMapping
,
671 uno_Environment
* pFrom
, uno_Environment
* pTo
, rtl_uString
* pAddPurpose
)
674 MappingsData
& rData
= getMappingsData();
675 ClearableMutexGuard
aGuard( rData
.aMappingsMutex
);
677 const t_Mapping2Entry::const_iterator
iFind( rData
.aMapping2Entry
.find( *ppMapping
) );
678 if (iFind
== rData
.aMapping2Entry
.end())
680 OUString
aMappingName(
681 getMappingName( pFrom
, pTo
, pAddPurpose
? OUString(pAddPurpose
) : OUString() ) );
682 #if OSL_DEBUG_LEVEL > 2
683 OString
cstr( OUStringToOString( aMappingName
, RTL_TEXTENCODING_ASCII_US
) );
684 OSL_TRACE( "> inserting new mapping: %s", cstr
.getStr() );
687 MappingEntry
* pEntry
= new MappingEntry( *ppMapping
, freeMapping
, aMappingName
);
688 rData
.aName2Entry
[ aMappingName
] = pEntry
;
689 rData
.aMapping2Entry
[ *ppMapping
] = pEntry
;
693 MappingEntry
* pEntry
= (*iFind
).second
;
696 if (pEntry
->pMapping
!= *ppMapping
) // exchange mapping to be registered
698 (*pEntry
->pMapping
->acquire
)( pEntry
->pMapping
);
699 --pEntry
->nRef
; // correct count; kill mapping to be registered
701 (*freeMapping
)( *ppMapping
);
702 *ppMapping
= pEntry
->pMapping
;
706 //##################################################################################################
707 CPPU_DLLPUBLIC
void SAL_CALL
uno_revokeMapping(
708 uno_Mapping
* pMapping
)
711 MappingsData
& rData
= getMappingsData();
712 ClearableMutexGuard
aGuard( rData
.aMappingsMutex
);
714 const t_Mapping2Entry::const_iterator
iFind( rData
.aMapping2Entry
.find( pMapping
) );
715 OSL_ASSERT( iFind
!= rData
.aMapping2Entry
.end() );
716 MappingEntry
* pEntry
= (*iFind
).second
;
717 if (! --pEntry
->nRef
)
719 rData
.aMapping2Entry
.erase( pEntry
->pMapping
);
720 rData
.aName2Entry
.erase( pEntry
->aMappingName
);
722 #if OSL_DEBUG_LEVEL > 2
723 OString
cstr( OUStringToOString( pEntry
->aMappingName
, RTL_TEXTENCODING_ASCII_US
) );
724 OSL_TRACE( "> revoking mapping %s", cstr
.getStr() );
726 (*pEntry
->freeMapping
)( pEntry
->pMapping
);
731 //##################################################################################################
732 CPPU_DLLPUBLIC
void SAL_CALL
uno_registerMappingCallback(
733 uno_getMappingFunc pCallback
)
736 OSL_ENSURE( pCallback
, "### null ptr!" );
737 MappingsData
& rData
= getMappingsData();
738 MutexGuard
aGuard( rData
.aCallbacksMutex
);
739 rData
.aCallbacks
.insert( pCallback
);
741 //##################################################################################################
742 CPPU_DLLPUBLIC
void SAL_CALL
uno_revokeMappingCallback(
743 uno_getMappingFunc pCallback
)
746 OSL_ENSURE( pCallback
, "### null ptr!" );
747 MappingsData
& rData
= getMappingsData();
748 MutexGuard
aGuard( rData
.aCallbacksMutex
);
749 rData
.aCallbacks
.erase( pCallback
);
753 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */