| OLD | NEW |
| 1 /* | 1 /* |
| 2 *******************************************************************************
***** | 2 *******************************************************************************
***** |
| 3 * Copyright (C) 2006-2014, International Business Machines Corporation | 3 * Copyright (C) 2006-2015, International Business Machines Corporation |
| 4 * and others. All Rights Reserved. | 4 * and others. All Rights Reserved. |
| 5 *******************************************************************************
***** | 5 *******************************************************************************
***** |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "unicode/utypes.h" | 8 #include "unicode/utypes.h" |
| 9 | 9 |
| 10 #if !UCONFIG_NO_BREAK_ITERATION | 10 #if !UCONFIG_NO_BREAK_ITERATION |
| 11 | 11 |
| 12 #include "brkeng.h" | 12 #include "brkeng.h" |
| 13 #include "dictbe.h" | 13 #include "dictbe.h" |
| 14 #include "unicode/uchar.h" | 14 #include "unicode/uchar.h" |
| 15 #include "unicode/uniset.h" | 15 #include "unicode/uniset.h" |
| 16 #include "unicode/chariter.h" | 16 #include "unicode/chariter.h" |
| 17 #include "unicode/ures.h" | 17 #include "unicode/ures.h" |
| 18 #include "unicode/udata.h" | 18 #include "unicode/udata.h" |
| 19 #include "unicode/putil.h" | 19 #include "unicode/putil.h" |
| 20 #include "unicode/ustring.h" | 20 #include "unicode/ustring.h" |
| 21 #include "unicode/uscript.h" | 21 #include "unicode/uscript.h" |
| 22 #include "unicode/ucharstrie.h" | 22 #include "unicode/ucharstrie.h" |
| 23 #include "unicode/bytestrie.h" | 23 #include "unicode/bytestrie.h" |
| 24 #include "charstr.h" | 24 #include "charstr.h" |
| 25 #include "dictionarydata.h" | 25 #include "dictionarydata.h" |
| 26 #include "mutex.h" |
| 26 #include "uvector.h" | 27 #include "uvector.h" |
| 27 #include "umutex.h" | 28 #include "umutex.h" |
| 28 #include "uresimp.h" | 29 #include "uresimp.h" |
| 29 #include "ubrkimpl.h" | 30 #include "ubrkimpl.h" |
| 30 | 31 |
| 31 U_NAMESPACE_BEGIN | 32 U_NAMESPACE_BEGIN |
| 32 | 33 |
| 33 /* | 34 /* |
| 34 ****************************************************************** | 35 ****************************************************************** |
| 35 */ | 36 */ |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 } | 132 } |
| 132 | 133 |
| 133 U_NAMESPACE_END | 134 U_NAMESPACE_END |
| 134 U_CDECL_BEGIN | 135 U_CDECL_BEGIN |
| 135 static void U_CALLCONV _deleteEngine(void *obj) { | 136 static void U_CALLCONV _deleteEngine(void *obj) { |
| 136 delete (const icu::LanguageBreakEngine *) obj; | 137 delete (const icu::LanguageBreakEngine *) obj; |
| 137 } | 138 } |
| 138 U_CDECL_END | 139 U_CDECL_END |
| 139 U_NAMESPACE_BEGIN | 140 U_NAMESPACE_BEGIN |
| 140 | 141 |
| 142 static UMutex gBreakEngineMutex = U_MUTEX_INITIALIZER; |
| 143 |
| 141 const LanguageBreakEngine * | 144 const LanguageBreakEngine * |
| 142 ICULanguageBreakFactory::getEngineFor(UChar32 c, int32_t breakType) { | 145 ICULanguageBreakFactory::getEngineFor(UChar32 c, int32_t breakType) { |
| 143 UBool needsInit; | |
| 144 int32_t i; | |
| 145 const LanguageBreakEngine *lbe = NULL; | 146 const LanguageBreakEngine *lbe = NULL; |
| 146 UErrorCode status = U_ZERO_ERROR; | 147 UErrorCode status = U_ZERO_ERROR; |
| 147 | 148 |
| 148 // TODO: The global mutex should not be used. | 149 Mutex m(&gBreakEngineMutex); |
| 149 // The global mutex should only be used for short periods. | 150 |
| 150 // A ICULanguageBreakFactory specific mutex should be used. | 151 if (fEngines == NULL) { |
| 151 umtx_lock(NULL); | 152 UStack *engines = new UStack(_deleteEngine, NULL, status); |
| 152 needsInit = (UBool)(fEngines == NULL); | 153 if (U_FAILURE(status) || engines == NULL) { |
| 153 if (!needsInit) { | 154 // Note: no way to return error code to caller. |
| 154 i = fEngines->size(); | 155 delete engines; |
| 156 return NULL; |
| 157 } |
| 158 fEngines = engines; |
| 159 } else { |
| 160 int32_t i = fEngines->size(); |
| 155 while (--i >= 0) { | 161 while (--i >= 0) { |
| 156 lbe = (const LanguageBreakEngine *)(fEngines->elementAt(i)); | 162 lbe = (const LanguageBreakEngine *)(fEngines->elementAt(i)); |
| 157 if (lbe != NULL && lbe->handles(c, breakType)) { | 163 if (lbe != NULL && lbe->handles(c, breakType)) { |
| 158 break; | 164 return lbe; |
| 159 } | 165 } |
| 160 lbe = NULL; | |
| 161 } | |
| 162 } | |
| 163 umtx_unlock(NULL); | |
| 164 | |
| 165 if (lbe != NULL) { | |
| 166 return lbe; | |
| 167 } | |
| 168 | |
| 169 if (needsInit) { | |
| 170 UStack *engines = new UStack(_deleteEngine, NULL, status); | |
| 171 if (U_SUCCESS(status) && engines == NULL) { | |
| 172 status = U_MEMORY_ALLOCATION_ERROR; | |
| 173 } | |
| 174 else if (U_FAILURE(status)) { | |
| 175 delete engines; | |
| 176 engines = NULL; | |
| 177 } | |
| 178 else { | |
| 179 umtx_lock(NULL); | |
| 180 if (fEngines == NULL) { | |
| 181 fEngines = engines; | |
| 182 engines = NULL; | |
| 183 } | |
| 184 umtx_unlock(NULL); | |
| 185 delete engines; | |
| 186 } | 166 } |
| 187 } | 167 } |
| 188 | 168 |
| 189 if (fEngines == NULL) { | 169 // We didn't find an engine. Create one. |
| 190 return NULL; | 170 lbe = loadEngineFor(c, breakType); |
| 171 if (lbe != NULL) { |
| 172 fEngines->push((void *)lbe, status); |
| 191 } | 173 } |
| 192 | |
| 193 // We didn't find an engine the first time through, or there was no | |
| 194 // stack. Create an engine. | |
| 195 const LanguageBreakEngine *newlbe = loadEngineFor(c, breakType); | |
| 196 | |
| 197 // Now get the lock, and see if someone else has created it in the | |
| 198 // meantime | |
| 199 umtx_lock(NULL); | |
| 200 i = fEngines->size(); | |
| 201 while (--i >= 0) { | |
| 202 lbe = (const LanguageBreakEngine *)(fEngines->elementAt(i)); | |
| 203 if (lbe != NULL && lbe->handles(c, breakType)) { | |
| 204 break; | |
| 205 } | |
| 206 lbe = NULL; | |
| 207 } | |
| 208 if (lbe == NULL && newlbe != NULL) { | |
| 209 fEngines->push((void *)newlbe, status); | |
| 210 lbe = newlbe; | |
| 211 newlbe = NULL; | |
| 212 } | |
| 213 umtx_unlock(NULL); | |
| 214 | |
| 215 delete newlbe; | |
| 216 | |
| 217 return lbe; | 174 return lbe; |
| 218 } | 175 } |
| 219 | 176 |
| 220 const LanguageBreakEngine * | 177 const LanguageBreakEngine * |
| 221 ICULanguageBreakFactory::loadEngineFor(UChar32 c, int32_t breakType) { | 178 ICULanguageBreakFactory::loadEngineFor(UChar32 c, int32_t breakType) { |
| 222 UErrorCode status = U_ZERO_ERROR; | 179 UErrorCode status = U_ZERO_ERROR; |
| 223 UScriptCode code = uscript_getScript(c, &status); | 180 UScriptCode code = uscript_getScript(c, &status); |
| 224 if (U_SUCCESS(status)) { | 181 if (U_SUCCESS(status)) { |
| 225 DictionaryMatcher *m = loadDictionaryMatcherFor(code, breakType); | 182 DictionaryMatcher *m = loadDictionaryMatcherFor(code, breakType); |
| 226 if (m != NULL) { | 183 if (m != NULL) { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 // returning NULL here will cause us to fail to find a dictionary break
engine, as expected | 291 // returning NULL here will cause us to fail to find a dictionary break
engine, as expected |
| 335 status = U_ZERO_ERROR; | 292 status = U_ZERO_ERROR; |
| 336 return NULL; | 293 return NULL; |
| 337 } | 294 } |
| 338 return NULL; | 295 return NULL; |
| 339 } | 296 } |
| 340 | 297 |
| 341 U_NAMESPACE_END | 298 U_NAMESPACE_END |
| 342 | 299 |
| 343 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ | 300 #endif /* #if !UCONFIG_NO_BREAK_ITERATION */ |
| OLD | NEW |