ICU-2787 add u_init() to work around thread safety problems with existing lazy init
X-SVN-Rev: 11735
This commit is contained in:
parent
7672ca8952
commit
702ddea7c2
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "unicode/uclean.h"
|
||||
#include "unicode/uchar.h"
|
||||
#include "ucln_cmn.h"
|
||||
#include "umutex.h"
|
||||
#include "ucln.h"
|
||||
@ -82,3 +83,46 @@ u_cleanup(void)
|
||||
umtx_destroy(NULL);
|
||||
}
|
||||
|
||||
|
||||
static UMTX InitMutex = NULL;
|
||||
|
||||
U_CAPI void U_EXPORT2
|
||||
u_init(UErrorCode *status) {
|
||||
/*
|
||||
* Lock and unlock the global mutex, thus forcing into existence
|
||||
* if it hasn't already been created.
|
||||
*/
|
||||
umtx_lock(NULL);
|
||||
umtx_unlock(NULL);
|
||||
|
||||
|
||||
/* Lock a private mutex for the duration of the initialization,
|
||||
* ensuring that there are no races through here, and to serve as
|
||||
* a memory barrier. Don't use the global mutex, because of the
|
||||
* possibility that some of the functions called within here might
|
||||
* use it.
|
||||
*/
|
||||
umtx_lock(&InitMutex);
|
||||
|
||||
/*
|
||||
* Do a simple operation using each of the data-requiring APIs that do
|
||||
* not have a service object, ensuring that the required data is loaded.
|
||||
*/
|
||||
|
||||
|
||||
/* Char Properties */
|
||||
u_hasBinaryProperty(0x20, UCHAR_WHITE_SPACE);
|
||||
|
||||
/* Char Names */
|
||||
{
|
||||
char buf[100];
|
||||
u_charName(0x20, U_UNICODE_CHAR_NAME, buf, 100, status);
|
||||
}
|
||||
|
||||
|
||||
/* TODO: the rest of 'em */
|
||||
|
||||
|
||||
umtx_unlock(&InitMutex);
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,31 @@
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
/**
|
||||
* Initialize ICU. This function loads and initializes data items
|
||||
* that are required internally by various ICU functions. Use of this explicit
|
||||
* initialization is required in multi-threaded applications; in
|
||||
* single threaded apps, use is optional, but incurs little additional
|
||||
* cost, and is thus recommended.
|
||||
* <p>
|
||||
* In multi-threaded applications, u_init() should be called in the
|
||||
* main thread before starting additional threads, or, alternatively
|
||||
* it can be called in each individual thread once, before other ICU
|
||||
* functions are called in that thread. In this second scenario, the
|
||||
* application must guarantee that the first call to u_init() happen
|
||||
* without contention, in a single thread only.
|
||||
* <p>
|
||||
* Extra, repeated, or otherwise unneeded calls to u_init() do no harm,
|
||||
* other taking a small amount of time.
|
||||
*
|
||||
* @param pErrorCode An ICU UErrorCode parameter. It must not be <code>NULL</code>.
|
||||
* An Error will be retuned if some required part of ICU data can not
|
||||
* be loaded or initialized.
|
||||
*
|
||||
*/
|
||||
U_CAPI void U_EXPORT2
|
||||
u_init(UErrorCode *status);
|
||||
|
||||
/**
|
||||
* Clean up the system resources, such as allocated memory or open files,
|
||||
* used in all ICU libraries. This will free/delete all memory owned by the
|
||||
@ -39,10 +64,10 @@
|
||||
* results.
|
||||
* <p>
|
||||
* After calling u_cleanup(), an application may continue to use ICU by
|
||||
* creating an ICU C++ object or opening new items (converters, collators,
|
||||
* etc.) and using them. An application must use ICU from one single
|
||||
* thread before allowing other threads or processes from using ICU. This
|
||||
* is so that the ICU libraries can reinitialize in a thread safe manner.
|
||||
* calling u_init(). An application must invoke u_init() first from one single
|
||||
* thread before allowing other threads call u_init(). All threads existing
|
||||
* at the time of the first thread's call to u_init() must also call
|
||||
* u_init() themselves before continuing with other ICU operations.
|
||||
* <p>
|
||||
* The use of u_cleanup() just before an application terminates is optional,
|
||||
* but it should be called only once for performance reasons. The primary
|
||||
|
@ -1064,6 +1064,19 @@ main(int argc, char* argv[])
|
||||
fprintf(stdout, " Leaks (l) : %s\n", (leaks? "On" : "Off"));
|
||||
fprintf(stdout, "-----------------------------------------------\n");
|
||||
|
||||
// Check that u_init() works
|
||||
errorCode = U_ZERO_ERROR;
|
||||
u_init(&errorCode);
|
||||
if (U_FAILURE(errorCode)) {
|
||||
fprintf(stdout,
|
||||
"*** u_init() failed with error code = %s\n"
|
||||
"*** Check the ICU_DATA environment variable and\n"
|
||||
"*** check that the data files are present.\n",
|
||||
u_errorName(errorCode));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// initial check for the default converter
|
||||
errorCode = U_ZERO_ERROR;
|
||||
cnv = ucnv_open(0, &errorCode);
|
||||
|
Loading…
Reference in New Issue
Block a user