ICU-11601 UConverterSharedData: add isReferenceCounted, stop checking for special referenceCounter=~0 value outside mutex to make thread sanitizer happy, remove long-unused table pointer field, add & use initializer macro

X-SVN-Rev: 37476
This commit is contained in:
Markus Scherer 2015-05-29 19:33:24 +00:00
parent 67134a6313
commit 2ad94b4e93
16 changed files with 73 additions and 238 deletions

View file

@ -1,7 +1,7 @@
/*
******************************************************************************
*
* Copyright (C) 1998-2013, International Business Machines
* Copyright (C) 1998-2015, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
@ -295,12 +295,7 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U
}
/* increment refcount of shared data if needed */
/*
Checking whether it's an algorithic converter is okay
in multithreaded applications because the value never changes.
Don't check referenceCounter for any other value.
*/
if (cnv->sharedData->referenceCounter != ~0) {
if (cnv->sharedData->isReferenceCounted) {
ucnv_incrementRefCount(cnv->sharedData);
}
@ -385,12 +380,7 @@ ucnv_close (UConverter * converter)
uprv_free(converter->subChars);
}
/*
Checking whether it's an algorithic converter is okay
in multithreaded applications because the value never changes.
Don't check referenceCounter for any other value.
*/
if (converter->sharedData->referenceCounter != ~0) {
if (converter->sharedData->isReferenceCounted) {
ucnv_unloadSharedDataIfReady(converter->sharedData);
}

View file

@ -3806,16 +3806,8 @@ static const UConverterStaticData _ISO2022StaticData={
0,
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _ISO2022Data={
sizeof(UConverterSharedData),
~((uint32_t) 0),
NULL,
NULL,
&_ISO2022StaticData,
FALSE,
&_ISO2022Impl,
0, UCNV_MBCS_TABLE_INITIALIZER
};
const UConverterSharedData _ISO2022Data=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_ISO2022StaticData, &_ISO2022Impl);
/*************JP****************/
static const UConverterImpl _ISO2022JPImpl={
@ -3862,16 +3854,8 @@ static const UConverterStaticData _ISO2022JPStaticData={
namespace {
const UConverterSharedData _ISO2022JPData={
sizeof(UConverterSharedData),
~((uint32_t) 0),
NULL,
NULL,
&_ISO2022JPStaticData,
FALSE,
&_ISO2022JPImpl,
0, UCNV_MBCS_TABLE_INITIALIZER
};
const UConverterSharedData _ISO2022JPData=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_ISO2022JPStaticData, &_ISO2022JPImpl);
} // namespace
@ -3921,16 +3905,8 @@ static const UConverterStaticData _ISO2022KRStaticData={
namespace {
const UConverterSharedData _ISO2022KRData={
sizeof(UConverterSharedData),
~((uint32_t) 0),
NULL,
NULL,
&_ISO2022KRStaticData,
FALSE,
&_ISO2022KRImpl,
0, UCNV_MBCS_TABLE_INITIALIZER
};
const UConverterSharedData _ISO2022KRData=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_ISO2022KRStaticData, &_ISO2022KRImpl);
} // namespace
@ -3980,16 +3956,8 @@ static const UConverterStaticData _ISO2022CNStaticData={
namespace {
const UConverterSharedData _ISO2022CNData={
sizeof(UConverterSharedData),
~((uint32_t) 0),
NULL,
NULL,
&_ISO2022CNStaticData,
FALSE,
&_ISO2022CNImpl,
0, UCNV_MBCS_TABLE_INITIALIZER
};
const UConverterSharedData _ISO2022CNData=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_ISO2022CNStaticData, &_ISO2022CNImpl);
} // namespace
#endif /* #if !UCONFIG_ONLY_HTML_CONVERSION */

View file

@ -292,6 +292,7 @@ ucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCo
if( (uint16_t)type >= UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES ||
converterData[type] == NULL ||
!converterData[type]->isReferenceCounted ||
converterData[type]->referenceCounter != 1 ||
source->structSize != sizeof(UConverterStaticData))
{
@ -308,26 +309,6 @@ ucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCo
/* copy initial values from the static structure for this type */
uprv_memcpy(data, converterData[type], sizeof(UConverterSharedData));
#if 0 /* made UConverterMBCSTable part of UConverterSharedData -- markus 20031107 */
/*
* It would be much more efficient if the table were a direct member, not a pointer.
* However, that would add to the size of all UConverterSharedData objects
* even if they do not use this table (especially algorithmic ones).
* If this changes, then the static templates from converterData[type]
* need more entries.
*
* In principle, it would be cleaner if the load() function below
* allocated the table.
*/
data->table = (UConverterTable *)uprv_malloc(sizeof(UConverterTable));
if(data->table == NULL) {
uprv_free(data);
*status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
uprv_memset(data->table, 0, sizeof(UConverterTable));
#endif
data->staticData = source;
data->sharedDataCached = FALSE;
@ -338,7 +319,6 @@ ucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCo
if(data->impl->load != NULL) {
data->impl->load(data, pArgs, raw + source->structSize, status);
if(U_FAILURE(*status)) {
uprv_free(data->table);
uprv_free(data);
return NULL;
}
@ -542,25 +522,6 @@ ucnv_deleteSharedConverterData(UConverterSharedData * deadSharedData)
udata_close(data);
}
if(deadSharedData->table != NULL)
{
uprv_free(deadSharedData->table);
}
#if 0
/* if the static data is actually owned by the shared data */
/* enable if we ever have this situation. */
if(deadSharedData->staticDataOwned == TRUE) /* see ucnv_bld.h */
{
uprv_free((void*)deadSharedData->staticData);
}
#endif
#if 0
/* Zap it ! */
uprv_memset(deadSharedData->0, sizeof(*deadSharedData));
#endif
uprv_free(deadSharedData);
UTRACE_EXIT_VALUE((int32_t)TRUE);
@ -611,7 +572,7 @@ ucnv_load(UConverterLoadArgs *pArgs, UErrorCode *err) {
/**
* Unload a non-algorithmic converter.
* It must be sharedData->referenceCounter != ~0
* It must be sharedData->isReferenceCounted
* and this function must be called inside umtx_lock(&cnvCacheMutex).
*/
U_CAPI void
@ -630,12 +591,7 @@ ucnv_unload(UConverterSharedData *sharedData) {
U_CFUNC void
ucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData)
{
/*
Checking whether it's an algorithic converter is okay
in multithreaded applications because the value never changes.
Don't check referenceCounter for any other value.
*/
if(sharedData != NULL && sharedData->referenceCounter != (uint32_t)~0) {
if(sharedData != NULL && sharedData->isReferenceCounted) {
umtx_lock(&cnvCacheMutex);
ucnv_unload(sharedData);
umtx_unlock(&cnvCacheMutex);
@ -645,12 +601,7 @@ ucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData)
U_CFUNC void
ucnv_incrementRefCount(UConverterSharedData *sharedData)
{
/*
Checking whether it's an algorithic converter is okay
in multithreaded applications because the value never changes.
Don't check referenceCounter for any other value.
*/
if(sharedData != NULL && sharedData->referenceCounter != (uint32_t)~0) {
if(sharedData != NULL && sharedData->isReferenceCounted) {
umtx_lock(&cnvCacheMutex);
sharedData->referenceCounter++;
umtx_unlock(&cnvCacheMutex);
@ -940,12 +891,7 @@ ucnv_createAlgorithmicConverter(UConverter *myUConverter,
}
sharedData = converterData[type];
/*
Checking whether it's an algorithic converter is okay
in multithreaded applications because the value never changes.
Don't check referenceCounter for any other value.
*/
if(sharedData == NULL || sharedData->referenceCounter != (uint32_t)~0) {
if(sharedData == NULL || sharedData->isReferenceCounted) {
/* not a valid type, or not an algorithmic converter */
*err = U_ILLEGAL_ARGUMENT_ERROR;
UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR);

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 1999-2011 International Business Machines
* Copyright (C) 1999-2015 International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*
@ -93,15 +93,15 @@ typedef struct UConverterStaticData { /* +offset: size */
*/
struct UConverterSharedData {
uint32_t structSize; /* Size of this structure */
uint32_t referenceCounter; /* used to count number of clients, 0xffffffff for static SharedData */
uint32_t referenceCounter; /* used to count number of clients, unused for static/immutable SharedData */
const void *dataMemory; /* from udata_openChoice() - for cleanup */
void *table; /* Unused. This used to be a UConverterTable - Pointer to conversion data - see mbcs below */
const UConverterStaticData *staticData; /* pointer to the static (non changing) data. */
UBool sharedDataCached; /* TRUE: shared data is in cache, don't destroy on ucnv_close() if 0 ref. FALSE: shared data isn't in the cache, do attempt to clean it up if the ref is 0 */
/*UBool staticDataOwned; TRUE if static data owned by shared data & should be freed with it, NEVER true for udata() loaded statics. This ignored variable was removed to make space for sharedDataCached. */
/** If FALSE, then referenceCounter is not used. Must not change after initialization. */
UBool isReferenceCounted;
const UConverterImpl *impl; /* vtable-style struct of mostly function pointers */
@ -115,16 +115,21 @@ struct UConverterSharedData {
* which always has a UConverterMBCSTable
*
* To eliminate one allocation, I am making the UConverterMBCSTable
* a member of the shared data. It is the last member so that static
* definitions of UConverterSharedData work as before.
* The table field above also remains to avoid updating all static
* definitions, but is now unused.
* a member of the shared data.
*
* markus 2003-nov-07
*/
UConverterMBCSTable mbcs;
};
/** UConverterSharedData initializer for static, non-reference-counted converters. */
#define UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(pStaticData, pImpl) \
{ \
sizeof(UConverterSharedData), ~((uint32_t)0), \
NULL, pStaticData, FALSE, FALSE, pImpl, \
0, UCNV_MBCS_TABLE_INITIALIZER \
}
/* Defines a UConverter, the lightweight mutable part the user sees */
struct UConverter {
@ -266,7 +271,7 @@ ucnv_load(UConverterLoadArgs *pArgs, UErrorCode *err);
/**
* Unload a non-algorithmic converter.
* It must be sharedData->referenceCounter != ~0
* It must be sharedData->isReferenceCounted
* and this function must be called inside umtx_lock(&cnvCacheMutex).
*/
U_CAPI void

View file

@ -629,15 +629,7 @@ static const UConverterStaticData _CompoundTextStaticData = {
0,
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _CompoundTextData = {
sizeof(UConverterSharedData),
~((uint32_t) 0),
NULL,
NULL,
&_CompoundTextStaticData,
FALSE,
&_CompoundTextImpl,
0
};
const UConverterSharedData _CompoundTextData =
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_CompoundTextStaticData, &_CompoundTextImpl);
#endif /* #if !UCONFIG_NO_LEGACY_CONVERSION */

View file

@ -606,11 +606,8 @@ static const UConverterStaticData _LMBCSStaticData##n={\
0, UCNV_IBM, UCNV_LMBCS_##n, 1, 3,\
{ 0x3f, 0, 0, 0 },1,FALSE,FALSE,0,0,{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} \
};\
const UConverterSharedData _LMBCSData##n={\
sizeof(UConverterSharedData), ~((uint32_t) 0),\
NULL, NULL, &_LMBCSStaticData##n, FALSE, &_LMBCSImpl##n, \
0 \
};
const UConverterSharedData _LMBCSData##n= \
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_LMBCSStaticData##n, &_LMBCSImpl##n);
/* The only function we needed to duplicate 12 times was the 'open'
function, which will do basically the same thing except set a different

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2002-2010, International Business Machines
* Copyright (C) 2002-2015, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* file name: ucnv_u16.c
@ -635,11 +635,8 @@ static const UConverterStaticData _UTF16BEStaticData={
};
const UConverterSharedData _UTF16BEData={
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_UTF16BEStaticData, FALSE, &_UTF16BEImpl,
0
};
const UConverterSharedData _UTF16BEData=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16BEStaticData, &_UTF16BEImpl);
/* UTF-16LE ----------------------------------------------------------------- */
@ -1235,11 +1232,8 @@ static const UConverterStaticData _UTF16LEStaticData={
};
const UConverterSharedData _UTF16LEData={
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_UTF16LEStaticData, FALSE, &_UTF16LEImpl,
0
};
const UConverterSharedData _UTF16LEData=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16LEStaticData, &_UTF16LEImpl);
/* UTF-16 (Detect BOM) ------------------------------------------------------ */
@ -1511,11 +1505,8 @@ static const UConverterStaticData _UTF16StaticData = {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _UTF16Data = {
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_UTF16StaticData, FALSE, &_UTF16Impl,
0
};
const UConverterSharedData _UTF16Data =
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16StaticData, &_UTF16Impl);
static const UConverterImpl _UTF16v2Impl = {
UCNV_UTF16,
@ -1552,10 +1543,7 @@ static const UConverterStaticData _UTF16v2StaticData = {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
static const UConverterSharedData _UTF16v2Data = {
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_UTF16v2StaticData, FALSE, &_UTF16v2Impl,
0
};
static const UConverterSharedData _UTF16v2Data =
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF16v2StaticData, &_UTF16v2Impl);
#endif

View file

@ -495,11 +495,8 @@ static const UConverterStaticData _UTF32BEStaticData = {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _UTF32BEData = {
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_UTF32BEStaticData, FALSE, &_UTF32BEImpl,
0
};
const UConverterSharedData _UTF32BEData =
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF32BEStaticData, &_UTF32BEImpl);
/* UTF-32LE ---------------------------------------------------------- */
@ -991,11 +988,8 @@ static const UConverterStaticData _UTF32LEStaticData = {
};
const UConverterSharedData _UTF32LEData = {
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_UTF32LEStaticData, FALSE, &_UTF32LEImpl,
0
};
const UConverterSharedData _UTF32LEData =
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF32LEStaticData, &_UTF32LEImpl);
/* UTF-32 (Detect BOM) ------------------------------------------------------ */
@ -1240,10 +1234,7 @@ static const UConverterStaticData _UTF32StaticData = {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _UTF32Data = {
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_UTF32StaticData, FALSE, &_UTF32Impl,
0
};
const UConverterSharedData _UTF32Data =
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF32StaticData, &_UTF32Impl);
#endif

View file

@ -775,11 +775,8 @@ static const UConverterStaticData _UTF7StaticData={
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _UTF7Data={
sizeof(UConverterSharedData), ~((uint32_t)0),
NULL, NULL, &_UTF7StaticData, FALSE, &_UTF7Impl,
0
};
const UConverterSharedData _UTF7Data=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF7StaticData, &_UTF7Impl);
/* IMAP mailbox name encoding ----------------------------------------------- */
@ -1475,10 +1472,7 @@ static const UConverterStaticData _IMAPStaticData={
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _IMAPData={
sizeof(UConverterSharedData), ~((uint32_t)0),
NULL, NULL, &_IMAPStaticData, FALSE, &_IMAPImpl,
0
};
const UConverterSharedData _IMAPData=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_IMAPStaticData, &_IMAPImpl);
#endif

View file

@ -1043,11 +1043,8 @@ static const UConverterStaticData _UTF8StaticData={
};
const UConverterSharedData _UTF8Data={
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_UTF8StaticData, FALSE, &_UTF8Impl,
0
};
const UConverterSharedData _UTF8Data=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_UTF8StaticData, &_UTF8Impl);
/* CESU-8 converter data ---------------------------------------------------- */
@ -1086,10 +1083,7 @@ static const UConverterStaticData _CESU8StaticData={
};
const UConverterSharedData _CESU8Data={
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_CESU8StaticData, FALSE, &_CESU8Impl,
0
};
const UConverterSharedData _CESU8Data=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_CESU8StaticData, &_CESU8Impl);
#endif

View file

@ -1388,11 +1388,7 @@ static const UConverterStaticData _Bocu1StaticData={
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _Bocu1Data={
sizeof(UConverterSharedData), ~((uint32_t)0),
NULL, NULL, &_Bocu1StaticData, FALSE, &_Bocu1Impl,
0,
UCNV_MBCS_TABLE_INITIALIZER
};
const UConverterSharedData _Bocu1Data=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_Bocu1StaticData, &_Bocu1Impl);
#endif

View file

@ -622,17 +622,8 @@ static const UConverterStaticData _HZStaticData={
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* reserved */
};
const UConverterSharedData _HZData={
sizeof(UConverterSharedData),
~((uint32_t) 0),
NULL,
NULL,
&_HZStaticData,
FALSE,
&_HZImpl,
0
};
const UConverterSharedData _HZData=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_HZStaticData, &_HZImpl);
#endif /* #if !UCONFIG_NO_CONVERSION && !UCONFIG_NO_LEGACY_CONVERSION && !UCONFIG_ONLY_HTML_CONVERSION */

View file

@ -1617,15 +1617,7 @@ static const UConverterStaticData _ISCIIStaticData={
};
const UConverterSharedData _ISCIIData={
sizeof(UConverterSharedData),
~((uint32_t) 0),
NULL,
NULL,
&_ISCIIStaticData,
FALSE,
&_ISCIIImpl,
0
};
const UConverterSharedData _ISCIIData=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_ISCIIStaticData, &_ISCIIImpl);
#endif /* #if !UCONFIG_NO_LEGACY_CONVERSION */

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2000-2012, International Business Machines
* Copyright (C) 2000-2015, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* file name: ucnvlat1.cpp
@ -458,11 +458,8 @@ static const UConverterStaticData _Latin1StaticData={
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _Latin1Data={
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_Latin1StaticData, FALSE, &_Latin1Impl,
0
};
const UConverterSharedData _Latin1Data=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_Latin1StaticData, &_Latin1Impl);
/* US-ASCII ----------------------------------------------------------------- */
@ -735,10 +732,7 @@ static const UConverterStaticData _ASCIIStaticData={
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _ASCIIData={
sizeof(UConverterSharedData), ~((uint32_t) 0),
NULL, NULL, &_ASCIIStaticData, FALSE, &_ASCIIImpl,
0
};
const UConverterSharedData _ASCIIData=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_ASCIIStaticData, &_ASCIIImpl);
#endif

View file

@ -1,7 +1,7 @@
/*
******************************************************************************
*
* Copyright (C) 2000-2014, International Business Machines
* Copyright (C) 2000-2015, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
@ -510,7 +510,7 @@ static const UConverterImpl _MBCSImpl={
const UConverterSharedData _MBCSData={
sizeof(UConverterSharedData), 1,
NULL, NULL, NULL, FALSE, &_MBCSImpl,
NULL, NULL, FALSE, TRUE, &_MBCSImpl,
0, UCNV_MBCS_TABLE_INITIALIZER
};

View file

@ -2009,10 +2009,7 @@ static const UConverterStaticData _SCSUStaticData={
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } /* reserved */
};
const UConverterSharedData _SCSUData={
sizeof(UConverterSharedData), ~((uint32_t)0),
NULL, NULL, &_SCSUStaticData, FALSE, &_SCSUImpl,
0
};
const UConverterSharedData _SCSUData=
UCNV_IMMUTABLE_SHARED_DATA_INITIALIZER(&_SCSUStaticData, &_SCSUImpl);
#endif