static int32_t usprep_internal_flushCache(UBool noRefCount) { UStringPrepProfile * profile = NULL; UStringPrepKey * key = NULL; int32_t pos = -1; int32_t deletedNum = 0; const UHashElement * e; /* * if shared data hasn't even been lazy evaluated yet * return 0 */ umtx_lock(&usprepMutex); if (SHARED_DATA_HASHTABLE == NULL) { umtx_unlock(&usprepMutex); return 0; } /*creates an enumeration to iterate through every element in the table */ while ((e = uhash_nextElement(SHARED_DATA_HASHTABLE, &pos)) != NULL) { profile = (UStringPrepProfile *) e->value.pointer; key = (UStringPrepKey *) e->key.pointer; if ((noRefCount == FALSE && profile->refCount == 0) || noRefCount == TRUE) { deletedNum++; uhash_removeElement(SHARED_DATA_HASHTABLE, e); /* unload the data */ usprep_unload(profile); if (key->name != NULL) { uprv_free(key->name); key->name = NULL; } if (key->path != NULL) { uprv_free(key->path); key->path = NULL; } uprv_free(profile); uprv_free(key); } } umtx_unlock(&usprepMutex); return deletedNum; }
static UStringPrepProfile* usprep_getProfile(const char* path, const char* name, UErrorCode *status){ UStringPrepProfile* profile = NULL; initCache(status); if(U_FAILURE(*status)){ return NULL; } UStringPrepKey stackKey; /* * const is cast way to save malloc, strcpy and free calls * we use the passed in pointers for fetching the data from the * hash table which is safe */ stackKey.name = (char*) name; stackKey.path = (char*) path; /* fetch the data from the cache */ umtx_lock(usprepMutex()); profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); if(profile != NULL) { profile->refCount++; } umtx_unlock(usprepMutex()); if(profile == NULL) { /* else load the data and put the data in the cache */ LocalMemory<UStringPrepProfile> newProfile; if(newProfile.allocateInsteadAndReset() == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; return NULL; } /* load the data */ if(!loadData(newProfile.getAlias(), path, name, _SPREP_DATA_TYPE, status) || U_FAILURE(*status) ){ return NULL; } /* get the options */ newProfile->doNFKC = (UBool)((newProfile->indexes[_SPREP_OPTIONS] & _SPREP_NORMALIZATION_ON) > 0); newProfile->checkBiDi = (UBool)((newProfile->indexes[_SPREP_OPTIONS] & _SPREP_CHECK_BIDI_ON) > 0); LocalMemory<UStringPrepKey> key; LocalMemory<char> keyName; LocalMemory<char> keyPath; if( key.allocateInsteadAndReset() == NULL || keyName.allocateInsteadAndCopy(static_cast<int32_t>(uprv_strlen(name)+1)) == NULL || (path != NULL && keyPath.allocateInsteadAndCopy(static_cast<int32_t>(uprv_strlen(path)+1)) == NULL) ) { *status = U_MEMORY_ALLOCATION_ERROR; usprep_unload(newProfile.getAlias()); return NULL; } umtx_lock(usprepMutex()); // If another thread already inserted the same key/value, refcount and cleanup our thread data profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); if(profile != NULL) { profile->refCount++; usprep_unload(newProfile.getAlias()); } else { /* initialize the key members */ key->name = keyName.orphan(); uprv_strcpy(key->name, name); if(path != NULL){ key->path = keyPath.orphan(); uprv_strcpy(key->path, path); } profile = newProfile.orphan(); /* add the data object to the cache */ profile->refCount = 1; uhash_put(SHARED_DATA_HASHTABLE, key.orphan(), profile, status); } umtx_unlock(usprepMutex()); } return profile; }
static UStringPrepProfile* usprep_getProfile(const char* path, const char* name, UErrorCode *status){ UStringPrepProfile* profile = NULL; initCache(status); if(U_FAILURE(*status)){ return NULL; } UStringPrepKey stackKey; /* * const is cast way to save malloc, strcpy and free calls * we use the passed in pointers for fetching the data from the * hash table which is safe */ stackKey.name = (char*) name; stackKey.path = (char*) path; /* fetch the data from the cache */ profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); if(profile == NULL){ UStringPrepKey* key = (UStringPrepKey*) uprv_malloc(sizeof(UStringPrepKey)); if(key == NULL){ *status = U_MEMORY_ALLOCATION_ERROR; return NULL; } /* else load the data and put the data in the cache */ profile = (UStringPrepProfile*) uprv_malloc(sizeof(UStringPrepProfile)); if(profile == NULL){ *status = U_MEMORY_ALLOCATION_ERROR; uprv_free(key); return NULL; } /* initialize the data struct members */ uprv_memset(profile->indexes,0,sizeof(profile->indexes)); profile->mappingData = NULL; profile->sprepData = NULL; profile->refCount = 0; /* initialize the key memebers */ key->name = (char*) uprv_malloc(uprv_strlen(name)+1); if(key->name == NULL){ *status = U_MEMORY_ALLOCATION_ERROR; uprv_free(key); uprv_free(profile); return NULL; } uprv_strcpy(key->name, name); key->path=NULL; if(path != NULL){ key->path = (char*) uprv_malloc(uprv_strlen(path)+1); if(key->path == NULL){ *status = U_MEMORY_ALLOCATION_ERROR; uprv_free(key->path); uprv_free(key); uprv_free(profile); return NULL; } uprv_strcpy(key->path, path); } /* load the data */ if(!loadData(profile, path, name, _SPREP_DATA_TYPE, status) || U_FAILURE(*status) ){ return NULL; } /* get the options */ profile->doNFKC = (UBool)((profile->indexes[_SPREP_OPTIONS] & _SPREP_NORMALIZATION_ON) > 0); profile->checkBiDi = (UBool)((profile->indexes[_SPREP_OPTIONS] & _SPREP_CHECK_BIDI_ON) > 0); if(profile->checkBiDi) { profile->bdp = ubidi_getSingleton(status); if(U_FAILURE(*status)) { usprep_unload(profile); uprv_free(key->path); uprv_free(key); uprv_free(profile); return NULL; } } else { profile->bdp = NULL; } umtx_lock(&usprepMutex); /* add the data object to the cache */ uhash_put(SHARED_DATA_HASHTABLE, key, profile, status); umtx_unlock(&usprepMutex); } umtx_lock(&usprepMutex); /* increment the refcount */ profile->refCount++; umtx_unlock(&usprepMutex); return profile; }