ICU-3039 assorted threading changes and cleanups, in search of the elusive

threading failure.

X-SVN-Rev: 14564
This commit is contained in:
Andy Heninger 2004-02-23 04:36:02 +00:00
parent 0db5ea8076
commit cdbbd81e4a
10 changed files with 923 additions and 554 deletions

View file

@ -341,7 +341,7 @@ Locale::Locale( const char * newLanguage,
size += 1; // at least: _v
}
if ( newKeywords != NULL)
if ( newKeywords != NULL)
{
ksize = (int32_t)uprv_strlen(newKeywords);
size += ksize + 1;
@ -613,17 +613,25 @@ Locale::setToBogus() {
const Locale&
Locale::getDefault()
{
const Locale *retLocale;
umtx_lock(NULL);
UBool needInit = (gDefaultLocale == NULL);
retLocale = gDefaultLocale;
umtx_unlock(NULL);
if (needInit) {
if (retLocale == NULL) {
umtx_lock(NULL);
/* uprv_getDefaultLocaleID is not thread safe, so we surround it with a mutex */
const char *cLocale = uprv_getDefaultLocaleID();
umtx_unlock(NULL);
locale_set_default_internal(cLocale);
umtx_lock(NULL);
// Need a mutex in case some other thread set a new
// default inbetween when we set and when we get the new default. For
// processors with weak memory coherency, we might not otherwise see all
// of the newly created new default locale.
retLocale = gDefaultLocale;
umtx_unlock(NULL);
}
return *gDefaultLocale;
return *retLocale;
}

View file

@ -48,6 +48,7 @@
#include "unicode/utypes.h"
#include "unicode/resbund.h"
#include "umutex.h"
#include "uresimp.h"
@ -172,52 +173,52 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ResourceBundle)
ResourceBundle::ResourceBundle( const UnicodeString& path,
const Locale& locale,
UErrorCode& error)
:UObject(), locName(NULL)
:UObject(), fLocale(NULL)
{
constructForLocale(path, locale, error);
}
ResourceBundle::ResourceBundle(UErrorCode &err)
:UObject(), locName(NULL)
:UObject(), fLocale(NULL)
{
resource = ures_open(0, Locale::getDefault().getName(), &err);
fResource = ures_open(0, Locale::getDefault().getName(), &err);
}
ResourceBundle::ResourceBundle( const UnicodeString& path,
UErrorCode& error)
:UObject(), locName(NULL)
:UObject(), fLocale(NULL)
{
constructForLocale(path, Locale::getDefault(), error);
}
ResourceBundle::ResourceBundle(const ResourceBundle &other)
:UObject(other), locName(NULL)
:UObject(other), fLocale(NULL)
{
UErrorCode status = U_ZERO_ERROR;
if (other.resource) {
resource = ures_copyResb(0, other.resource, &status);
if (other.fResource) {
fResource = ures_copyResb(0, other.fResource, &status);
} else {
/* Copying a bad resource bundle */
resource = NULL;
fResource = NULL;
}
}
ResourceBundle::ResourceBundle(UResourceBundle *res, UErrorCode& err)
:UObject(), locName(NULL)
:UObject(), fLocale(NULL)
{
if (res) {
resource = ures_copyResb(0, res, &err);
fResource = ures_copyResb(0, res, &err);
} else {
/* Copying a bad resource bundle */
resource = NULL;
fResource = NULL;
}
}
ResourceBundle::ResourceBundle(const char* path, const Locale& locale, UErrorCode& err)
:UObject(), locName(NULL)
:UObject(), fLocale(NULL)
{
resource = ures_open(path, locale.getName(), &err);
fResource = ures_open(path, locale.getName(), &err);
}
@ -226,27 +227,27 @@ ResourceBundle& ResourceBundle::operator=(const ResourceBundle& other)
if(this == &other) {
return *this;
}
if(resource != 0) {
ures_close(resource);
resource = NULL;
if(fResource != 0) {
ures_close(fResource);
fResource = NULL;
}
UErrorCode status = U_ZERO_ERROR;
if (other.resource) {
resource = ures_copyResb(0, other.resource, &status);
if (other.fResource) {
fResource = ures_copyResb(0, other.fResource, &status);
} else {
/* Copying a bad resource bundle */
resource = NULL;
fResource = NULL;
}
return *this;
}
ResourceBundle::~ResourceBundle()
{
if(resource != 0) {
ures_close(resource);
if(fResource != 0) {
ures_close(fResource);
}
if(locName != NULL) {
delete(locName);
if(fLocale != NULL) {
delete(fLocale);
}
}
@ -264,63 +265,63 @@ ResourceBundle::constructForLocale(const UnicodeString& path,
if(!path.isEmpty()) {
path.extract(name, sizeof(name), 0, error);
resource = ures_open(name, locale.getName(), &error);
fResource = ures_open(name, locale.getName(), &error);
} else {
resource = ures_open(0, locale.getName(), &error);
fResource = ures_open(0, locale.getName(), &error);
}
}
UnicodeString ResourceBundle::getString(UErrorCode& status) const {
int32_t len = 0;
const UChar *r = ures_getString(resource, &len, &status);
const UChar *r = ures_getString(fResource, &len, &status);
return UnicodeString(TRUE, r, len);
}
const uint8_t *ResourceBundle::getBinary(int32_t& len, UErrorCode& status) const {
return ures_getBinary(resource, &len, &status);
return ures_getBinary(fResource, &len, &status);
}
const int32_t *ResourceBundle::getIntVector(int32_t& len, UErrorCode& status) const {
return ures_getIntVector(resource, &len, &status);
return ures_getIntVector(fResource, &len, &status);
}
uint32_t ResourceBundle::getUInt(UErrorCode& status) const {
return ures_getUInt(resource, &status);
return ures_getUInt(fResource, &status);
}
int32_t ResourceBundle::getInt(UErrorCode& status) const {
return ures_getInt(resource, &status);
return ures_getInt(fResource, &status);
}
const char *ResourceBundle::getName(void) {
return ures_getName(resource);
return ures_getName(fResource);
}
const char *ResourceBundle::getKey(void) {
return ures_getKey(resource);
return ures_getKey(fResource);
}
UResType ResourceBundle::getType(void) {
return ures_getType(resource);
return ures_getType(fResource);
}
int32_t ResourceBundle::getSize(void) const {
return ures_getSize(resource);
return ures_getSize(fResource);
}
UBool ResourceBundle::hasNext(void) const {
return ures_hasNext(resource);
return ures_hasNext(fResource);
}
void ResourceBundle::resetIterator(void) {
ures_resetIterator(resource);
ures_resetIterator(fResource);
}
ResourceBundle ResourceBundle::getNext(UErrorCode& status) {
UResourceBundle r;
ures_initStackObject(&r);
ures_getNextResource(resource, &r, &status);
ures_getNextResource(fResource, &r, &status);
ResourceBundle res(&r, status);
if (U_SUCCESS(status)) {
ures_close(&r);
@ -330,13 +331,13 @@ ResourceBundle ResourceBundle::getNext(UErrorCode& status) {
UnicodeString ResourceBundle::getNextString(UErrorCode& status) {
int32_t len = 0;
const UChar* r = ures_getNextString(resource, &len, 0, &status);
const UChar* r = ures_getNextString(fResource, &len, 0, &status);
return UnicodeString(TRUE, r, len);
}
UnicodeString ResourceBundle::getNextString(const char ** key, UErrorCode& status) {
int32_t len = 0;
const UChar* r = ures_getNextString(resource, &len, key, &status);
const UChar* r = ures_getNextString(fResource, &len, key, &status);
return UnicodeString(TRUE, r, len);
}
@ -344,7 +345,7 @@ ResourceBundle ResourceBundle::get(int32_t indexR, UErrorCode& status) const {
UResourceBundle r;
ures_initStackObject(&r);
ures_getByIndex(resource, indexR, &r, &status);
ures_getByIndex(fResource, indexR, &r, &status);
ResourceBundle res(&r, status);
if (U_SUCCESS(status)) {
ures_close(&r);
@ -354,7 +355,7 @@ ResourceBundle ResourceBundle::get(int32_t indexR, UErrorCode& status) const {
UnicodeString ResourceBundle::getStringEx(int32_t indexS, UErrorCode& status) const {
int32_t len = 0;
const UChar* r = ures_getStringByIndex(resource, indexS, &len, &status);
const UChar* r = ures_getStringByIndex(fResource, indexS, &len, &status);
return UnicodeString(TRUE, r, len);
}
@ -362,7 +363,7 @@ ResourceBundle ResourceBundle::get(const char* key, UErrorCode& status) const {
UResourceBundle r;
ures_initStackObject(&r);
ures_getByKey(resource, key, &r, &status);
ures_getByKey(fResource, key, &r, &status);
ResourceBundle res(&r, status);
if (U_SUCCESS(status)) {
ures_close(&r);
@ -372,34 +373,45 @@ ResourceBundle ResourceBundle::get(const char* key, UErrorCode& status) const {
UnicodeString ResourceBundle::getStringEx(const char* key, UErrorCode& status) const {
int32_t len = 0;
const UChar* r = ures_getStringByKey(resource, key, &len, &status);
const UChar* r = ures_getStringByKey(fResource, key, &len, &status);
return UnicodeString(TRUE, r, len);
}
const char*
ResourceBundle::getVersionNumber() const
{
return ures_getVersionNumber(resource);
return ures_getVersionNumber(fResource);
}
void ResourceBundle::getVersion(UVersionInfo versionInfo) const {
ures_getVersion(resource, versionInfo);
ures_getVersion(fResource, versionInfo);
}
const Locale &ResourceBundle::getLocale(void) const
{
if(locName == NULL) {
UErrorCode status = U_ZERO_ERROR;
const char *localeName = ures_getLocale(resource, &status);
ResourceBundle *me = (ResourceBundle *)this; // semantically const
me->locName = new Locale(localeName);
}
return *locName;
UBool needInit;
umtx_lock(NULL);
needInit = (fLocale == NULL);
umtx_unlock(NULL);
if(needInit) {
UErrorCode status = U_ZERO_ERROR;
const char *localeName = ures_getLocale(fResource, &status);
Locale *tLocale = new Locale(localeName);
umtx_lock(NULL);
ResourceBundle *me = (ResourceBundle *)this; // semantically const
if (me->fLocale == NULL) {
me->fLocale = tLocale;
tLocale = NULL;
}
umtx_unlock(NULL);
delete tLocale;
}
return *fLocale;
}
const Locale ResourceBundle::getLocale(ULocDataLocaleType type, UErrorCode &status) const
{
return ures_getLocaleByType(resource, type, &status);
return ures_getLocaleByType(fResource, type, &status);
}
//eof

View file

@ -84,34 +84,62 @@
*
*/
/* The global ICU mutex. */
#if defined(WIN32)
static UMTX gGlobalMutex = NULL;
#define MAX_MUTEXES 30
static char gMutexesInUse[MAX_MUTEXES];
static UBool gMutexPoolInitialized = FALSE;
static UMTX gGlobalMutex = NULL;
static UMTX gIncDecMutex = NULL;
/*-------------------------------------------------------------
*
* WINDOWS platform variable declarations
*
*-------------------------------------------------------------*/
#if defined(WIN32)
static CRITICAL_SECTION gMutexes[MAX_MUTEXES];
static CRITICAL_SECTION gGlobalWinMutex;
/* Detect Recursive locking of the global mutex. For debugging only. */
#if defined(_DEBUG) && (ICU_USE_THREADS==1)
static int32_t gRecursionCount = 0;
#endif
/*-------------------------------------------------------------
*
* POSIX platform variable declarations
*
*-------------------------------------------------------------*/
#elif defined(POSIX)
#if (ICU_USE_THREADS == 1)
static pthread_mutex_t gGlobalPosixMutex = PTHREAD_MUTEX_INITIALIZER;
static UMTX gGlobalMutex = &gGlobalPosixMutex;
static UMTX gIncDecMutex = NULL;
#else
static UMTX gGlobalMutex = NULL;
static UMTX gIncDecMutex = NULL;
static pthread_mutex_t gMutexes[MAX_MUTEXES] = {
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER
};
#endif
/*-------------------------------------------------------------
*
* UNKNOWN platform declarations
*
*-------------------------------------------------------------*/
#else
/* Unknown platform. OK so long as ICU_USE_THREAD is not set.
Note that user can still set mutex functions at run time,
and that the global mutex variable is still needed in that case. */
static UMTX gGlobalMutex = NULL;
#if (ICU_USE_THREADS == 1)
#error no ICU mutex implementation for this platform
#endif
#endif
/* Detect Recursive locking of the global mutex. For debugging only. */
#if defined(WIN32) && defined(_DEBUG) && (ICU_USE_THREADS==1)
static int32_t gRecursionCount = 0;
#endif
/*
@ -202,50 +230,6 @@ umtx_unlock(UMTX* mutex)
/*
* umtx_raw_init Do the platform specific mutex allocation and initialization
* for all ICU mutexes _except_ the ICU global mutex.
*/
static void umtx_raw_init(UMTX *mutex) {
if (pMutexInitFn != NULL) {
UErrorCode status = U_ZERO_ERROR;
(*pMutexInitFn)(gMutexContext, mutex, &status);
if (U_FAILURE(status)) {
/* TODO: how should errors here be handled? */
return;
}
} else {
#if (ICU_USE_THREADS == 1)
#if defined (WIN32)
CRITICAL_SECTION *cs = uprv_malloc(sizeof(CRITICAL_SECTION));
if (cs == NULL) {
return;
}
InitializeCriticalSection(cs);
*mutex = cs;
#elif defined( POSIX )
pthread_mutex_t *m = (pthread_mutex_t *)uprv_malloc(sizeof(pthread_mutex_t));
if (m == NULL) {
return;
}
# if defined (HPUX_CMA)
pthread_mutex_init(m, pthread_mutexattr_default);
# else
pthread_mutex_init(m, NULL);
# endif
*mutex = m;
#endif /* cascade of platforms */
#else /* ICU_USE_THREADS */
*mutex = mutex; /* With no threads, we must still set the mutex to
* some non-null value to make the rest of the
* (not ifdefed) mutex code think that it is initialized.
*/
#endif /* ICU_USE_THREADS */
}
}
/*
* initGlobalMutex Do the platform specific initialization of the ICU global mutex.
@ -254,9 +238,11 @@ static void umtx_raw_init(UMTX *mutex) {
* without the use of another mutex.
*/
static void initGlobalMutex() {
int i;
/*
* Call user mutex init function if one has been specified and the global mutex
* is not already initialized.
* If User Supplied mutex functions are in use
* init the icu global mutex using them.
*/
if (pMutexInitFn != NULL) {
if (gGlobalMutex==NULL) {
@ -274,31 +260,34 @@ static void initGlobalMutex() {
* Use default ICU mutex implementations.
*/
#if (ICU_USE_THREADS == 1)
/*
* for Windows, init the pool of critical sections that we
* will use as needed for ICU mutexes.
*/
#if defined (WIN32)
{
void *t;
CRITICAL_SECTION *ourCritSec = uprv_malloc(sizeof(CRITICAL_SECTION));
InitializeCriticalSection(ourCritSec);
#if defined (InterlockedCompareExchangePointer) || defined (_WIN64)
t = InterlockedCompareExchangePointer(&gGlobalMutex, ourCritSec, NULL);
#else
/* Note that the headers from Microsoft's WIndows SDK define InterlockedCompareExchangePointer
* for all platforms, but the old headers included with MSVC 6 do not.
*/
t = (void *)InterlockedCompareExchange(&gGlobalMutex, ourCritSec, NULL);
#endif
if (t != NULL) {
/* Some other thread stored into gGlobalMutex first. Discard the critical
* section we just created; the system will go with the other one.
*/
DeleteCriticalSection(ourCritSec);
uprv_free(ourCritSec);
if (gMutexPoolInitialized == FALSE) {
for (i=0; i<MAX_MUTEXES; i++) {
InitializeCriticalSection(&gMutexes[i]);
}
}
#elif defined( POSIX )
/* No Action Required. Global mutex set up with C static initialization. */
U_ASSERT(gGlobalMutex == &gGlobalPosixMutex);
#endif /* cascade of platforms */
gMutexPoolInitialized = TRUE;
#elif defined (POSIX)
/* TODO: experimental code. Shouldn't need to explicitly init the mutexes. */
if (gMutexPoolInitialized == FALSE) {
for (i=0; i<MAX_MUTEXES; i++) {
pthread_mutex_init(&gMutexes[i], NULL);
}
}
gMutexPoolInitialized = TRUE;
#endif
/*
* for both Windows & POSIX, the first mutex in the array is used
* for the ICU global mutex.
*/
gGlobalMutex = &gMutexes[0];
gMutexesInUse[0] = 1;
#else /* ICU_USE_THREADS */
gGlobalMutex = &gGlobalMutex; /* With no threads, we must still set the mutex to
* some non-null value to make the rest of the
@ -317,32 +306,36 @@ umtx_init(UMTX *mutex)
if (mutex == NULL || mutex == &gGlobalMutex) {
initGlobalMutex();
} else {
/*
* Thread safe initialization of mutexes other than the global one,
* using the global mutex.
*/
UBool isInitialized;
UMTX tMutex = NULL;
int i;
umtx_lock(NULL);
isInitialized = (*mutex != NULL);
umtx_unlock(NULL);
if (isInitialized) {
if (*mutex != NULL) {
/* Another thread initialized this mutex first. */
umtx_unlock(NULL);
return;
}
umtx_raw_init(&tMutex);
if (pMutexInitFn != NULL) {
UErrorCode status = U_ZERO_ERROR;
(*pMutexInitFn)(gMutexContext, mutex, &status);
/* TODO: how to report failure on init? */
umtx_unlock(NULL);
return;
}
umtx_lock(NULL);
if (*mutex == NULL) {
*mutex = tMutex;
tMutex = NULL;
/* Search through our pool of pre-allocated mutexes for one that is not
* already in use. */
for (i=0; i<MAX_MUTEXES; i++) {
if (gMutexesInUse[i] == 0) {
gMutexesInUse[i] = 1;
*mutex = &gMutexes[i];
break;
}
}
umtx_unlock(NULL);
if (tMutex != NULL) {
umtx_destroy(&tMutex);
}
/* No more mutexes were available from our pre-allocated pool. */
/* TODO: how best to deal with this? */
U_ASSERT(*mutex != NULL);
}
}
@ -364,38 +357,28 @@ umtx_destroy(UMTX *mutex) {
return;
}
#if defined (POSIX)
/* The life of the inc/dec mutex for POSIX is tied to that of the global mutex. */
/* The life of the inc/dec mutex is tied to that of the global mutex. */
if (mutex == &gGlobalMutex) {
umtx_destroy(&gIncDecMutex);
}
#endif
if (pMutexDestroyFn != NULL) {
/* Mutexes are being managed by the app. Call back to it for the destroy. */
(*pMutexDestroyFn)(gMutexContext, mutex);
*mutex = NULL;
} else {
#if (ICU_USE_THREADS == 1)
#if defined (WIN32)
DeleteCriticalSection((CRITICAL_SECTION*)*mutex);
uprv_free(*mutex);
*mutex = NULL;
#elif defined (POSIX)
if (*mutex != &gGlobalPosixMutex) {
/* Only POSIX mutexes other than the ICU global mutex get destroyed. */
pthread_mutex_destroy((pthread_mutex_t*)*mutex);
uprv_free(*mutex);
*mutex = NULL;
}
#endif /* chain of platforms */
#else /* ICU_USE_THREADS==1 */
/* NO ICU Threads. We still need to zero out the mutex pointer, so that
* it appears to be uninitialized */
*mutex = NULL;
#endif /* ICU_USE_THREADS */
/* Return this mutex to the pool of available mutexes, if it came from the
* pool in the first place.
*/
int i;
for (i=0; i<MAX_MUTEXES; i++) {
if (*mutex == &gMutexes[i]) {
gMutexesInUse[i] = 0;
break;
}
}
}
*mutex = NULL;
}
@ -528,22 +511,35 @@ u_setAtomicIncDecFunctions(const void *context, UMtxAtomicFn *ip, UMtxAtomicFn *
* Destroy the global mutex(es), and reset the mutex function callback pointers.
*/
U_CFUNC UBool umtx_cleanup(void) {
int i;
umtx_destroy(NULL);
pMutexInitFn = NULL;
pMutexDestroyFn = NULL;
pMutexLockFn = NULL;
pMutexUnlockFn = NULL;
gMutexContext = NULL;
gGlobalMutex = NULL;
#if defined (POSIX)
gIncDecMutex = NULL;
#if (ICU_USE_THREADS == 1)
gGlobalMutex = &gGlobalPosixMutex;
#endif
#endif
pIncFn = NULL;
pDecFn = NULL;
gIncDecMutex = NULL;
#if defined (WIN32)
if (gMutexPoolInitialized) {
for (i=0; i<MAX_MUTEXES; i++) {
DeleteCriticalSection(&gMutexes[i]);
gMutexesInUse[i] = 0;
}
}
gMutexPoolInitialized = FALSE;
#elif defined (POSIX)
gIncDecMutex = NULL;
for (i=0; i<MAX_MUTEXES; i++) {
pthread_mutex_destroy(&gMutexes[i]);
gMutexesInUse[i] = 0;
}
gMutexPoolInitialized = FALSE;
#endif
return TRUE;
}

View file

@ -457,9 +457,9 @@ public:
private:
ResourceBundle(); // default constructor not implemented
UResourceBundle *resource;
UResourceBundle *fResource;
void constructForLocale(const UnicodeString& path, const Locale& locale, UErrorCode& error);
Locale *locName;
Locale *fLocale;
};

View file

@ -246,6 +246,7 @@ static void setEntryName(UResourceDataEntry *res, char *name, UErrorCode *status
/**
* INTERNAL: Inits and opens an entry from a data DLL.
* CAUTION: resbMutex must be locked when calling this function.
*/
static UResourceDataEntry *init_entry(const char *localeID, const char *path, UErrorCode *status) {
UResourceDataEntry *r = NULL;
@ -377,6 +378,7 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE
}
/* INTERNAL: */
/* CAUTION: resbMutex must be locked when calling this function! */
static UResourceDataEntry *findFirstExisting(const char* path, char* name, UBool *isRoot, UBool *hasChopped, UBool *isDefault, UErrorCode* status) {
UResourceDataEntry *r = NULL;
UBool hasRealData = FALSE;
@ -517,6 +519,7 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, UEr
/**
* Functions to create and destroy resource bundles.
* CAUTION: resbMutex must be locked when calling this function.
*/
/* INTERNAL: */
static void entryCloseInt(UResourceDataEntry *resB) {

View file

@ -18,11 +18,14 @@
#include "rbt_data.h"
#include "rbt_rule.h"
#include "rbt.h"
#include "umutex.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedTransliterator)
static UMTX transliteratorDataMutex = NULL;
void RuleBasedTransliterator::_construct(const UnicodeString& rules,
UTransDirection direction,
UParseError& parseError,
@ -228,7 +231,7 @@ RuleBasedTransliterator::handleTransliterate(Replaceable& text, UTransPosition&
}
if (isDataOwned==FALSE) {
fData->lock();
umtx_lock(&transliteratorDataMutex);
}
while (index.start < index.limit &&
loopCount <= loopLimit &&
@ -236,7 +239,7 @@ RuleBasedTransliterator::handleTransliterate(Replaceable& text, UTransPosition&
++loopCount;
}
if (isDataOwned==FALSE) {
fData->unlock();
umtx_unlock(&transliteratorDataMutex);
}
}

View file

@ -23,7 +23,7 @@ U_NAMESPACE_BEGIN
TransliterationRuleData::TransliterationRuleData(UErrorCode& status)
: UMemory(), ruleSet(status),
variableNames(0), variables(0), fLock(NULL)
variableNames(0), variables(0)
{
if (U_FAILURE(status)) {
return;
@ -44,8 +44,7 @@ TransliterationRuleData::TransliterationRuleData(UErrorCode& status)
TransliterationRuleData::TransliterationRuleData(const TransliterationRuleData& other) :
UMemory(other), ruleSet(other.ruleSet),
variablesBase(other.variablesBase),
variablesLength(other.variablesLength),
fLock(NULL) /* The mutex must NOT be copied from the source data */
variablesLength(other.variablesLength)
{
UErrorCode status = U_ZERO_ERROR;
variableNames = new Hashtable(status);
@ -85,7 +84,6 @@ TransliterationRuleData::~TransliterationRuleData() {
}
uprv_free(variables);
}
umtx_destroy(&fLock);
}
UnicodeFunctor*
@ -106,17 +104,6 @@ TransliterationRuleData::lookupReplacer(UChar32 standIn) const {
return (f != 0) ? f->toReplacer() : 0;
}
void
TransliterationRuleData::lock() {
umtx_lock(&fLock);
}
void
TransliterationRuleData::unlock() {
umtx_unlock(&fLock);
}
U_NAMESPACE_END

View file

@ -130,19 +130,9 @@ public:
*/
UnicodeReplacer* lookupReplacer(UChar32 standIn) const;
/**
* Acquire the mutex lock for this data.
*/
void lock();
/**
* Release the mutex lock for this data
*/
void unlock();
private:
TransliterationRuleData &operator=(const TransliterationRuleData &other); // forbid copying of this class
UMTX fLock;
};
U_NAMESPACE_END

File diff suppressed because it is too large Load diff

View file

@ -11,25 +11,6 @@
#include "intltest.h"
#include "mutex.h"
/*
Test multithreading. Of course we need a thread class first..
this wrapper has a ported implementation.
*/
class SimpleThread
{
public:
SimpleThread();
virtual ~SimpleThread();
int32_t start(void); // start the thread
public: // should be private, but then we couldn't be asocial.
virtual void run(void) = 0; // Override this to provide some real implementation
private:
void *fImplementation;
public:
static void sleep(int32_t millis); // probably shouldn't go here but oh well.
};
/**
@ -58,7 +39,7 @@ public:
void TestThreadedIntl(void);
#endif
void TestCollators(void);
void TestString();
};
#endif