X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/b331163bffd790ced0e88b73f44f86d49ccc48a5..f59164e3d128c7675a4d3934206346a3384e53a5:/icuSources/common/brkeng.cpp?ds=sidebyside diff --git a/icuSources/common/brkeng.cpp b/icuSources/common/brkeng.cpp index 2398fe9c..5b3cfa3a 100644 --- a/icuSources/common/brkeng.cpp +++ b/icuSources/common/brkeng.cpp @@ -1,6 +1,6 @@ /* ************************************************************************************ - * Copyright (C) 2006-2014, International Business Machines Corporation + * Copyright (C) 2006-2016, International Business Machines Corporation * and others. All Rights Reserved. ************************************************************************************ */ @@ -10,6 +10,7 @@ #if !UCONFIG_NO_BREAK_ITERATION #include "brkeng.h" +#include "cmemory.h" #include "dictbe.h" #include "unicode/uchar.h" #include "unicode/uniset.h" @@ -23,6 +24,7 @@ #include "unicode/bytestrie.h" #include "charstr.h" #include "dictionarydata.h" +#include "mutex.h" #include "uvector.h" #include "umutex.h" #include "uresimp.h" @@ -55,13 +57,13 @@ LanguageBreakFactory::~LanguageBreakFactory() { */ UnhandledEngine::UnhandledEngine(UErrorCode &/*status*/) { - for (int32_t i = 0; i < (int32_t)(sizeof(fHandled)/sizeof(fHandled[0])); ++i) { + for (int32_t i = 0; i < UPRV_LENGTHOF(fHandled); ++i) { fHandled[i] = 0; } } UnhandledEngine::~UnhandledEngine() { - for (int32_t i = 0; i < (int32_t)(sizeof(fHandled)/sizeof(fHandled[0])); ++i) { + for (int32_t i = 0; i < UPRV_LENGTHOF(fHandled); ++i) { if (fHandled[i] != 0) { delete fHandled[i]; } @@ -70,7 +72,7 @@ UnhandledEngine::~UnhandledEngine() { UBool UnhandledEngine::handles(UChar32 c, int32_t breakType) const { - return (breakType >= 0 && breakType < (int32_t)(sizeof(fHandled)/sizeof(fHandled[0])) + return (breakType >= 0 && breakType < UPRV_LENGTHOF(fHandled) && fHandled[breakType] != 0 && fHandled[breakType]->contains(c)); } @@ -81,7 +83,7 @@ UnhandledEngine::findBreaks( UText *text, UBool reverse, int32_t breakType, UStack &/*foundBreaks*/ ) const { - if (breakType >= 0 && breakType < (int32_t)(sizeof(fHandled)/sizeof(fHandled[0]))) { + if (breakType >= 0 && breakType < UPRV_LENGTHOF(fHandled)) { UChar32 c = utext_current32(text); if (reverse) { while((int32_t)utext_getNativeIndex(text) > startPos && fHandled[breakType]->contains(c)) { @@ -100,7 +102,7 @@ UnhandledEngine::findBreaks( UText *text, void UnhandledEngine::handleCharacter(UChar32 c, int32_t breakType) { - if (breakType >= 0 && breakType < (int32_t)(sizeof(fHandled)/sizeof(fHandled[0]))) { + if (breakType >= 0 && breakType < UPRV_LENGTHOF(fHandled)) { if (fHandled[breakType] == 0) { fHandled[breakType] = new UnicodeSet(); if (fHandled[breakType] == 0) { @@ -138,82 +140,38 @@ static void U_CALLCONV _deleteEngine(void *obj) { U_CDECL_END U_NAMESPACE_BEGIN +static UMutex gBreakEngineMutex = U_MUTEX_INITIALIZER; + const LanguageBreakEngine * ICULanguageBreakFactory::getEngineFor(UChar32 c, int32_t breakType) { - UBool needsInit; - int32_t i; const LanguageBreakEngine *lbe = NULL; UErrorCode status = U_ZERO_ERROR; - // TODO: The global mutex should not be used. - // The global mutex should only be used for short periods. - // A ICULanguageBreakFactory specific mutex should be used. - umtx_lock(NULL); - needsInit = (UBool)(fEngines == NULL); - if (!needsInit) { - i = fEngines->size(); + Mutex m(&gBreakEngineMutex); + + if (fEngines == NULL) { + UStack *engines = new UStack(_deleteEngine, NULL, status); + if (U_FAILURE(status) || engines == NULL) { + // Note: no way to return error code to caller. + delete engines; + return NULL; + } + fEngines = engines; + } else { + int32_t i = fEngines->size(); while (--i >= 0) { lbe = (const LanguageBreakEngine *)(fEngines->elementAt(i)); if (lbe != NULL && lbe->handles(c, breakType)) { - break; + return lbe; } - lbe = NULL; } } - umtx_unlock(NULL); + // We didn't find an engine. Create one. + lbe = loadEngineFor(c, breakType); if (lbe != NULL) { - return lbe; - } - - if (needsInit) { - UStack *engines = new UStack(_deleteEngine, NULL, status); - if (U_SUCCESS(status) && engines == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - } - else if (U_FAILURE(status)) { - delete engines; - engines = NULL; - } - else { - umtx_lock(NULL); - if (fEngines == NULL) { - fEngines = engines; - engines = NULL; - } - umtx_unlock(NULL); - delete engines; - } - } - - if (fEngines == NULL) { - return NULL; + fEngines->push((void *)lbe, status); } - - // We didn't find an engine the first time through, or there was no - // stack. Create an engine. - const LanguageBreakEngine *newlbe = loadEngineFor(c, breakType); - - // Now get the lock, and see if someone else has created it in the - // meantime - umtx_lock(NULL); - i = fEngines->size(); - while (--i >= 0) { - lbe = (const LanguageBreakEngine *)(fEngines->elementAt(i)); - if (lbe != NULL && lbe->handles(c, breakType)) { - break; - } - lbe = NULL; - } - if (lbe == NULL && newlbe != NULL) { - fEngines->push((void *)newlbe, status); - lbe = newlbe; - newlbe = NULL; - } - umtx_unlock(NULL); - - delete newlbe; - return lbe; }