- if (cacheDescriptorList._obj != NULL) {
- for (int32_t i = cacheDescriptorList._obj->size(); --i >= 0;) {
- UnicodeString* desc = (UnicodeString*)cacheDescriptorList._obj->elementAt(i);
- serviceCache->put(*desc, result, status);
+ do {
+ currentDescriptor.remove();
+ key.currentDescriptor(currentDescriptor);
+ result = (CacheEntry*)serviceCache->get(currentDescriptor);
+ if (result != NULL) {
+ break;
+ }
+
+ // first test of cache failed, so we'll have to update
+ // the cache if we eventually succeed-- that is, if we're
+ // going to update the cache at all.
+ putInCache = TRUE;
+
+ int32_t index = startIndex;
+ while (index < limit) {
+ ICUServiceFactory* f = (ICUServiceFactory*)factories->elementAt(index++);
+ UObject* service = f->create(key, this, status);
+ if (U_FAILURE(status)) {
+ delete service;
+ return NULL;
+ }
+ if (service != NULL) {
+ result = new CacheEntry(currentDescriptor, service);
+ if (result == NULL) {
+ delete service;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+
+ goto outerEnd;
+ }
+ }
+
+ // prepare to load the cache with all additional ids that
+ // will resolve to result, assuming we'll succeed. We
+ // don't want to keep querying on an id that's going to
+ // fallback to the one that succeeded, we want to hit the
+ // cache the first time next goaround.
+ if (cacheDescriptorList._obj == NULL) {
+ cacheDescriptorList._obj = new UVector(uprv_deleteUObject, NULL, 5, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ }
+ UnicodeString* idToCache = new UnicodeString(currentDescriptor);
+ if (idToCache == NULL || idToCache->isBogus()) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+
+ cacheDescriptorList._obj->addElement(idToCache, status);