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 |