const LanguageBreakEngine * ICULanguageBreakFactory::getEngineFor(UChar32 c, int32_t breakType) { const LanguageBreakEngine *lbe = NULL; UErrorCode status = U_ZERO_ERROR; 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)) { return lbe; } } } // We didn't find an engine. Create one. lbe = loadEngineFor(c, breakType); if (lbe != NULL) { fEngines->push((void *)lbe, status); } return lbe; }
U_CDECL_END U_NAMESPACE_BEGIN 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(); while (--i >= 0) { lbe = (const LanguageBreakEngine *)(fEngines->elementAt(i)); if (lbe != NULL && lbe->handles(c, breakType)) { break; } lbe = NULL; } } umtx_unlock(NULL); 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; } // 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; }