From: Travis Keep Date: Thu, 21 Aug 2014 21:02:57 +0000 (+0000) Subject: ICU-11075 Remove dead code including LRUCache and tests and sharedptr.h X-Git-Tag: milestone-59-0-1~1699 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9c4a5db3537e44914c9a54cb16bdd586c0bcd592;p=icu ICU-11075 Remove dead code including LRUCache and tests and sharedptr.h X-SVN-Rev: 36226 --- diff --git a/icu4c/source/common/Makefile.in b/icu4c/source/common/Makefile.in index 09b1bdf47fc..2d8b12c0ab0 100644 --- a/icu4c/source/common/Makefile.in +++ b/icu4c/source/common/Makefile.in @@ -104,7 +104,7 @@ rbbi.o rbbidata.o rbbinode.o rbbirb.o rbbiscan.o rbbisetb.o rbbistbl.o rbbitblb. serv.o servnotf.o servls.o servlk.o servlkf.o servrbf.o servslkf.o \ uidna.o usprep.o uts46.o punycode.o \ util.o util_props.o parsepos.o locbased.o cwchar.o wintz.o dtintrv.o ucnvsel.o propsvec.o \ -ulist.o uloc_tag.o icudataver.o icuplug.o listformatter.o lrucache.o \ +ulist.o uloc_tag.o icudataver.o icuplug.o listformatter.o \ sharedobject.o simplepatternformatter.o unifiedcache.o ## Header files to install diff --git a/icu4c/source/common/common.vcxproj b/icu4c/source/common/common.vcxproj index 506964ce13f..12f993feb41 100644 --- a/icu4c/source/common/common.vcxproj +++ b/icu4c/source/common/common.vcxproj @@ -368,9 +368,6 @@ - - false - @@ -1069,7 +1066,6 @@ ..\..\include\unicode\%(Filename)%(Extension);%(Outputs) - copy "%(FullPath)" ..\..\include\unicode @@ -1086,7 +1082,6 @@ - copy "%(FullPath)" ..\..\include\unicode diff --git a/icu4c/source/common/common.vcxproj.filters b/icu4c/source/common/common.vcxproj.filters index 82c8f13ebff..a4571cf92e8 100644 --- a/icu4c/source/common/common.vcxproj.filters +++ b/icu4c/source/common/common.vcxproj.filters @@ -103,9 +103,6 @@ collation - - collections - collections @@ -618,9 +615,6 @@ collections - - collections - collections @@ -714,9 +708,6 @@ data & memory - - data & memory - data & memory diff --git a/icu4c/source/common/lrucache.cpp b/icu4c/source/common/lrucache.cpp deleted file mode 100644 index a92d0388dcf..00000000000 --- a/icu4c/source/common/lrucache.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* -****************************************************************************** -* Copyright (C) 2014, International Business Machines Corporation and -* others. All Rights Reserved. -****************************************************************************** -* -* File LRUCACHE.CPP -****************************************************************************** -*/ - -#include "lrucache.h" -#include "uhash.h" -#include "cstring.h" -#include "uassert.h" - -U_NAMESPACE_BEGIN - -// TODO (Travis Keep): Consider building synchronization into this cache -// instead of leaving synchronization up to the clients. - -LRUCache::CacheEntry::CacheEntry() - : moreRecent(NULL), lessRecent(NULL), localeId(NULL), cachedData(NULL), - status(U_ZERO_ERROR) { -} - -LRUCache::CacheEntry::~CacheEntry() { - reset(); -} - -void LRUCache::CacheEntry::unlink() { - if (moreRecent != NULL) { - moreRecent->lessRecent = lessRecent; - } - if (lessRecent != NULL) { - lessRecent->moreRecent = moreRecent; - } - moreRecent = NULL; - lessRecent = NULL; -} - -void LRUCache::CacheEntry::reset() { - SharedObject::clearPtr(cachedData); - status = U_ZERO_ERROR; - uprv_free(localeId); - localeId = NULL; -} - -void LRUCache::CacheEntry::init( - char *adoptedLocId, SharedObject *dataToAdopt, UErrorCode err) { - U_ASSERT(localeId == NULL); - localeId = adoptedLocId; - SharedObject::copyPtr(dataToAdopt, cachedData); - status = err; -} - -void LRUCache::moveToMostRecent(CacheEntry *entry) { - if (entry->moreRecent == mostRecentlyUsedMarker) { - return; - } - entry->unlink(); - entry->moreRecent = mostRecentlyUsedMarker; - entry->lessRecent = mostRecentlyUsedMarker->lessRecent; - mostRecentlyUsedMarker->lessRecent->moreRecent = entry; - mostRecentlyUsedMarker->lessRecent = entry; -} - -void LRUCache::init(char *adoptedLocId, CacheEntry *entry) { - UErrorCode status = U_ZERO_ERROR; - SharedObject *result = create(adoptedLocId, status); - entry->init(adoptedLocId, result, status); -} - -UBool LRUCache::contains(const char *localeId) const { - return (uhash_get(localeIdToEntries, localeId) != NULL); -} - - -const SharedObject *LRUCache::_get(const char *localeId, UErrorCode &status) { - // TODO (Travis Keep): Consider stripping irrelevant locale keywords. - if (U_FAILURE(status)) { - return NULL; - } - CacheEntry *entry = static_cast(uhash_get( - localeIdToEntries, localeId)); - if (entry == NULL) { - // Its a cache miss. - - if (uhash_count(localeIdToEntries) < maxSize) { - // Cache not full. There is room for a new entry. - entry = new CacheEntry; - if (entry == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - } else { - // Cache full. Must evict an entry and re-use it. - entry = leastRecentlyUsedMarker->moreRecent; - uhash_remove(localeIdToEntries, entry->localeId); - entry->unlink(); - entry->reset(); - } - - // entry is an uninitialized, unlinked cache entry - char *dupLocaleId = uprv_strdup(localeId); - if (dupLocaleId == NULL) { - delete entry; - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - init(dupLocaleId, entry); - - // Entry is initialized, add to hashtable - uhash_put(localeIdToEntries, entry->localeId, entry, &status); - if (U_FAILURE(status)) { - delete entry; - return NULL; - } - } - - // Re-link entry so that it is the most recent. - moveToMostRecent(entry); - - if (U_FAILURE(entry->status)) { - status = entry->status; - return NULL; - } - return entry->cachedData; -} - -LRUCache::LRUCache(int32_t size, UErrorCode &status) : - mostRecentlyUsedMarker(NULL), - leastRecentlyUsedMarker(NULL), - localeIdToEntries(NULL), - maxSize(size) { - if (U_FAILURE(status)) { - return; - } - mostRecentlyUsedMarker = new CacheEntry; - leastRecentlyUsedMarker = new CacheEntry; - if (mostRecentlyUsedMarker == NULL || leastRecentlyUsedMarker == NULL) { - delete mostRecentlyUsedMarker; - delete leastRecentlyUsedMarker; - mostRecentlyUsedMarker = leastRecentlyUsedMarker = NULL; - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - mostRecentlyUsedMarker->moreRecent = NULL; - mostRecentlyUsedMarker->lessRecent = leastRecentlyUsedMarker; - leastRecentlyUsedMarker->moreRecent = mostRecentlyUsedMarker; - leastRecentlyUsedMarker->lessRecent = NULL; - localeIdToEntries = uhash_openSize( - uhash_hashChars, - uhash_compareChars, - NULL, - maxSize + maxSize / 5, - &status); - if (U_FAILURE(status)) { - return; - } -} - -LRUCache::~LRUCache() { - uhash_close(localeIdToEntries); - for (CacheEntry *i = mostRecentlyUsedMarker; i != NULL;) { - CacheEntry *next = i->lessRecent; - delete i; - i = next; - } -} - -SimpleLRUCache::~SimpleLRUCache() { -} - -SharedObject *SimpleLRUCache::create(const char *localeId, UErrorCode &status) { - return createFunc(localeId, status); -} - -U_NAMESPACE_END diff --git a/icu4c/source/common/lrucache.h b/icu4c/source/common/lrucache.h deleted file mode 100644 index 19675ed4889..00000000000 --- a/icu4c/source/common/lrucache.h +++ /dev/null @@ -1,147 +0,0 @@ -/* -****************************************************************************** -* Copyright (C) 2014, International Business Machines Corporation and -* others. All Rights Reserved. -****************************************************************************** -* -* File LRUCACHE.H -****************************************************************************** -*/ - -#ifndef __LRU_CACHE_H__ -#define __LRU_CACHE_H__ - -#include "unicode/uobject.h" -#include "sharedobject.h" - -struct UHashtable; - -U_NAMESPACE_BEGIN - -/** - * A cache of SharedObjects keyed by locale ID. - * - * LRUCache has one main method, get(), which fetches a SharedObject by - * locale ID. If no such SharedObject is cached, get() creates the new - * SharedObject and caches it behind the scenes. - * - * Each LRUCache has a maximum size. Whenever adding a new item to the cache - * would exceed this maximum size, LRUCache evicts the SharedObject that was - * least recently fetched via the get() method. - * - * LRUCache is designed to be subclassed. Subclasses must override the create() - * method to create a new SharedObject by localeId. If only locale ID is - * needed to create the SharedObject, a client can use SimpleLRUCache. - */ -class U_COMMON_API LRUCache : public UObject { -public: - /** - * Fetches a SharedObject by locale ID. On success, get() makes ptr point - * to the fetched SharedObject while automatically updating reference - * counts; on failure, get() leaves ptr unchanged and sets status. - * When get() is called, ptr must either be NULL or be included in the - * reference count of what it points to. After get() returns successfully, - * caller must eventually call removeRef() on ptr to avoid memory leaks. - * - * T must be a subclass of SharedObject. - */ - template - void get(const char *localeId, const T *&ptr, UErrorCode &status) { - const T *value = (const T *) _get(localeId, status); - if (U_FAILURE(status)) { - return; - } - SharedObject::copyPtr(value, ptr); - } - /** - * Returns TRUE if a SharedObject for given ID is cached. Used - * primarily for testing purposes. - */ - UBool contains(const char *localeId) const; - virtual ~LRUCache(); -protected: - /** - * Subclasses override to create a new SharedObject for given localeID. - * get() calls this to resolve cache misses. create() must either return - * a SharedObject with 0 reference count and no error in status or return - * NULL and set an error in status. - */ - virtual SharedObject *create(const char *localeId, UErrorCode &status)=0; - - /** - * Constructor. - * @param maxSize the maximum size of the LRUCache - * @param status any error is set here. - */ - LRUCache(int32_t maxSize, UErrorCode &status); -private: - class CacheEntry : public UMemory { - public: - CacheEntry *moreRecent; - CacheEntry *lessRecent; - char *localeId; - const SharedObject *cachedData; - UErrorCode status; // This is the error if any from creating - // cachedData. - CacheEntry(); - ~CacheEntry(); - - void unlink(); - void reset(); - void init( - char *adoptedLocId, SharedObject *dataToAdopt, UErrorCode err); - private: - CacheEntry(const CacheEntry& other); - CacheEntry &operator=(const CacheEntry& other); - }; - LRUCache(); - LRUCache(const LRUCache &other); - LRUCache &operator=(const LRUCache &other); - - // TODO (Travis Keep): Consider replacing both of these end nodes with a - // single sentinel. - CacheEntry *mostRecentlyUsedMarker; - CacheEntry *leastRecentlyUsedMarker; - UHashtable *localeIdToEntries; - int32_t maxSize; - - void moveToMostRecent(CacheEntry *cacheEntry); - void init(char *localeId, CacheEntry *cacheEntry); - const SharedObject *_get(const char *localeId, UErrorCode &status); -}; - -/** - * A function type that creates a SharedObject from a locale ID. Functions of - * this type must return a SharedObject with 0 reference count and no error in - * status or return NULL and set an error in status. - */ -typedef SharedObject *CreateFunc(const char *localeId, UErrorCode &status); - -/** - * A concrete subclass of LRUCache that creates SharedObjects using a - * function of type CreateFunc. - */ -class U_COMMON_API SimpleLRUCache : public LRUCache { -public: - /** - * Constructor. - * @param maxSize the maximum cache size. - * @param cf creates SharedObject on cache miss. - * @param status error reported here. - */ - SimpleLRUCache( - int32_t maxSize, - CreateFunc cf, - UErrorCode &status) : - LRUCache(maxSize, status), createFunc(cf) { - } - virtual ~SimpleLRUCache(); -protected: - virtual SharedObject *create(const char *localeId, UErrorCode &status); -private: - CreateFunc *createFunc; -}; - -U_NAMESPACE_END - -#endif diff --git a/icu4c/source/common/sharedptr.h b/icu4c/source/common/sharedptr.h deleted file mode 100644 index 31d62aaef6e..00000000000 --- a/icu4c/source/common/sharedptr.h +++ /dev/null @@ -1,225 +0,0 @@ -/* -******************************************************************************* -* Copyright (C) 2014, International Business Machines Corporation and -* others. All Rights Reserved. -******************************************************************************* -* -* File SHAREDPTR.H -******************************************************************************* -*/ - -#ifndef __SHARED_PTR_H__ -#define __SHARED_PTR_H__ - -#include "unicode/uobject.h" -#include "umutex.h" -#include "uassert.h" - -U_NAMESPACE_BEGIN - -// Wrap u_atomic_int32_t in a UMemory so that we allocate them in the same -// way we allocate all other ICU objects. -struct AtomicInt : public UMemory { - u_atomic_int32_t value; -}; - -/** - * SharedPtr are shared pointers that support copy-on-write sematics. - * SharedPtr makes the act of copying large objects cheap by deferring the - * cost of the copy to the first write operation after the copy. - * - * A SharedPtr instance can refer to no object or an object of type T. - * T must have a clone() method that copies - * the object and returns a pointer to the copy. Copy and assignment of - * SharedPtr instances are cheap because they only involve copying or - * assigning the SharedPtr instance, not the T object which could be large. - * Although many SharedPtr instances may refer to the same T object, - * clients can still assume that each SharedPtr instance has its own - * private instance of T because each SharedPtr instance offers only a - * const view of its T object through normal pointer operations. If a caller - * must change a T object through its SharedPtr, it can do so by calling - * readWrite() on the SharedPtr instance. readWrite() ensures that the - * SharedPtr really does have its own private T object by cloning it if - * it is shared by using its clone() method. SharedPtr instances handle - * management by reference counting their T objects. T objects that are - * referenced by no SharedPtr instances get deleted automatically. - */ - -// TODO (Travis Keep): Leave interface the same, but find a more efficient -// implementation that is easier to understand. -template -class SharedPtr { -public: - /** - * Constructor. If there is a memory allocation error creating - * reference counter then this object will contain NULL, and adopted - * pointer will be freed. Note that when passing NULL or no argument to - * constructor, no memory allocation error can happen as NULL pointers - * are never reference counted. - */ - explicit SharedPtr(T *adopted=NULL) : ptr(adopted), refPtr(NULL) { - if (ptr != NULL) { - refPtr = new AtomicInt(); - if (refPtr == NULL) { - delete ptr; - ptr = NULL; - } else { - refPtr->value = 1; - } - } - } - - /** - * Copy constructor. - */ - SharedPtr(const SharedPtr &other) : - ptr(other.ptr), refPtr(other.refPtr) { - if (refPtr != NULL) { - umtx_atomic_inc(&refPtr->value); - } - } - - /** - * assignment operator. - */ - SharedPtr &operator=(const SharedPtr &other) { - if (ptr != other.ptr) { - SharedPtr newValue(other); - swap(newValue); - } - return *this; - } - - /** - * Destructor. - */ - ~SharedPtr() { - if (refPtr != NULL) { - if (umtx_atomic_dec(&refPtr->value) == 0) { - delete ptr; - delete refPtr; - } - } - } - - /** - * reset adopts a new pointer. On success, returns TRUE. - * On memory allocation error creating reference counter for adopted - * pointer, returns FALSE while leaving this instance unchanged. - */ - bool reset(T *adopted) { - SharedPtr newValue(adopted); - if (adopted != NULL && newValue.ptr == NULL) { - // We couldn't allocate ref counter. - return FALSE; - } - swap(newValue); - return TRUE; - } - - /** - * reset makes this instance refer to no object. - */ - void reset() { - reset(NULL); - } - - /** - * count returns how many SharedPtr instances, including this one, - * refer to the T object. Used for testing. Clients need not use in - * practice. - */ - int32_t count() const { - if (refPtr == NULL) { - return 0; - } - return umtx_loadAcquire(refPtr->value); - } - - /** - * Swaps this instance with other. - */ - void swap(SharedPtr &other) { - T *tempPtr = other.ptr; - AtomicInt *tempRefPtr = other.refPtr; - other.ptr = ptr; - other.refPtr = refPtr; - ptr = tempPtr; - refPtr = tempRefPtr; - } - - const T *operator->() const { - return ptr; - } - - const T &operator*() const { - return *ptr; - } - - bool operator==(const T *other) const { - return ptr == other; - } - - bool operator!=(const T *other) const { - return ptr != other; - } - - /** - * readOnly gives const access to this instance's T object. If this - * instance refers to no object, returns NULL. - */ - const T *readOnly() const { - return ptr; - } - - /** - * readWrite returns a writable pointer to its T object copying it first - * using its clone() method if it is shared. - * On memory allocation error or if this instance refers to no object, - * this method returns NULL leaving this instance unchanged. - *

- * If readWrite() returns a non NULL pointer, it guarantees that this - * object holds the only reference to its T object enabling the caller to - * perform mutations using the returned pointer without affecting other - * SharedPtr objects. However, the non-constness of readWrite continues as - * long as the returned pointer is in scope. Therefore it is an API - * violation to call readWrite() on A; perform B = A; and then proceed to - * mutate A via its writeable pointer as that would be the same as setting - * B = A while A is changing. The returned pointer is guaranteed to be - * valid only while this object is in scope because this object maintains - * ownership of its T object. Therefore, callers must never attempt to - * delete the returned writeable pointer. The best practice with readWrite - * is this: callers should use the returned pointer from readWrite() only - * within the same scope as that call to readWrite, and that scope should - * be made as small as possible avoiding overlap with other operatios on - * this object. - */ - T *readWrite() { - int32_t refCount = count(); - if (refCount <= 1) { - return ptr; - } - T *result = (T *) ptr->clone(); - if (result == NULL) { - // Memory allocation error - return NULL; - } - if (!reset(result)) { - return NULL; - } - return ptr; - } -private: - T *ptr; - AtomicInt *refPtr; - // No heap allocation. Use only stack. - static void * U_EXPORT2 operator new(size_t size); - static void * U_EXPORT2 operator new[](size_t size); -#if U_HAVE_PLACEMENT_NEW - static void * U_EXPORT2 operator new(size_t, void *ptr); -#endif -}; - -U_NAMESPACE_END - -#endif diff --git a/icu4c/source/test/intltest/Makefile.in b/icu4c/source/test/intltest/Makefile.in index 47cf33fa8bb..1f01d49ca0b 100644 --- a/icu4c/source/test/intltest/Makefile.in +++ b/icu4c/source/test/intltest/Makefile.in @@ -57,7 +57,7 @@ uobjtest.o idnaref.o idnaconf.o nptrans.o punyref.o testidn.o testidna.o uts46te incaltst.o calcasts.o v32test.o uvectest.o textfile.o tokiter.o utxttest.o \ windttst.o winnmtst.o winutil.o csdetest.o tzrulets.o tzoffloc.o tzfmttst.o ssearch.o dtifmtts.o \ tufmtts.o itspoof.o simplethread.o bidiconf.o locnmtst.o dcfmtest.o alphaindextst.o listformattertest.o genderinfotest.o compactdecimalformattest.o regiontst.o \ -reldatefmttest.o lrucachetest.o simplepatternformattertest.o measfmttest.o scientificformathelpertest.o numfmtspectest.o unifiedcachetest.o +reldatefmttest.o simplepatternformattertest.o measfmttest.o scientificformathelpertest.o numfmtspectest.o unifiedcachetest.o DEPS = $(OBJECTS:.o=.d) diff --git a/icu4c/source/test/intltest/intltest.vcxproj b/icu4c/source/test/intltest/intltest.vcxproj index 5f6263ff1ee..47783d865c6 100644 --- a/icu4c/source/test/intltest/intltest.vcxproj +++ b/icu4c/source/test/intltest/intltest.vcxproj @@ -309,9 +309,6 @@ - - false - diff --git a/icu4c/source/test/intltest/intltest.vcxproj.filters b/icu4c/source/test/intltest/intltest.vcxproj.filters index 3a92940a8b6..8bb629841b4 100644 --- a/icu4c/source/test/intltest/intltest.vcxproj.filters +++ b/icu4c/source/test/intltest/intltest.vcxproj.filters @@ -136,9 +136,6 @@ collation - - collections - collections diff --git a/icu4c/source/test/intltest/itutil.cpp b/icu4c/source/test/intltest/itutil.cpp index 7e0e75c5d1a..75db2526923 100644 --- a/icu4c/source/test/intltest/itutil.cpp +++ b/icu4c/source/test/intltest/itutil.cpp @@ -33,7 +33,6 @@ extern IntlTest *createBytesTrieTest(); static IntlTest *createLocalPointerTest(); extern IntlTest *createUCharsTrieTest(); static IntlTest *createEnumSetTest(); -extern IntlTest *createLRUCacheTest(); extern IntlTest *createSimplePatternFormatterTest(); extern IntlTest *createUnifiedCacheTest(); @@ -99,14 +98,6 @@ void IntlTestUtilities::runIndexedTest( int32_t index, UBool exec, const char* & } break; case 20: - name = "LRUCacheTest"; - if (exec) { - logln("TestSuite LRUCacheTest---"); logln(); - LocalPointer test(createLRUCacheTest()); - callTest(*test, par); - } - break; - case 21: name = "SimplePatternFormatterTest"; if (exec) { logln("TestSuite SimplePatternFormatterTest---"); logln(); @@ -114,7 +105,7 @@ void IntlTestUtilities::runIndexedTest( int32_t index, UBool exec, const char* & callTest(*test, par); } break; - case 22: + case 21: name = "UnifiedCacheTest"; if (exec) { logln("TestSuite UnifiedCacheTest---"); logln(); diff --git a/icu4c/source/test/intltest/lrucachetest.cpp b/icu4c/source/test/intltest/lrucachetest.cpp deleted file mode 100644 index a304eb823af..00000000000 --- a/icu4c/source/test/intltest/lrucachetest.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/* -******************************************************************************* -* Copyright (C) 2014, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -* -* File LRUCACHETEST.CPP -* -******************************************************************************** -*/ -#include "cstring.h" -#include "intltest.h" -#include "lrucache.h" -#include "sharedptr.h" - -class CopyOnWriteForTesting : public SharedObject { -public: - CopyOnWriteForTesting() : SharedObject(), localeNamePtr(), formatStrPtr(), length(0) { - } - - CopyOnWriteForTesting(const CopyOnWriteForTesting &other) : - SharedObject(other), - localeNamePtr(other.localeNamePtr), - formatStrPtr(other.formatStrPtr), - length(other.length) { - } - - virtual ~CopyOnWriteForTesting() { - } - - SharedPtr localeNamePtr; - SharedPtr formatStrPtr; - int32_t length; -private: - CopyOnWriteForTesting &operator=(const CopyOnWriteForTesting &rhs); -}; - -class LRUCacheForTesting : public LRUCache { -public: - LRUCacheForTesting( - int32_t maxSize, - const UnicodeString &dfs, UErrorCode &status); - virtual ~LRUCacheForTesting() { - } -protected: - virtual SharedObject *create(const char *localeId, UErrorCode &status); -private: - SharedPtr defaultFormatStr; -}; - -LRUCacheForTesting::LRUCacheForTesting( - int32_t maxSize, - const UnicodeString &dfs, UErrorCode &status) : - LRUCache(maxSize, status), defaultFormatStr() { - if (U_FAILURE(status)) { - return; - } - defaultFormatStr.reset(new UnicodeString(dfs)); -} - -SharedObject *LRUCacheForTesting::create(const char *localeId, UErrorCode &status) { - if (uprv_strcmp(localeId, "error") == 0) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return NULL; - } - CopyOnWriteForTesting *result = new CopyOnWriteForTesting; - result->localeNamePtr.reset(new UnicodeString(localeId)); - result->formatStrPtr = defaultFormatStr; - result->length = 5; - return result; -} - -class LRUCacheTest : public IntlTest { -public: - LRUCacheTest() { - } - void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0); -private: - void TestSharedPointer(); - void TestErrorCallingConstructor(); - void TestLRUCache(); - void TestLRUCacheError(); - void verifySharedPointer( - const CopyOnWriteForTesting* ptr, - const UnicodeString& name, - const UnicodeString& format); - void verifyString( - const UnicodeString &expected, const UnicodeString &actual); - void verifyReferences( - const CopyOnWriteForTesting* ptr, - int32_t count, int32_t nameCount, int32_t formatCount); -}; - -void LRUCacheTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/) { - TESTCASE_AUTO_BEGIN; - TESTCASE_AUTO(TestSharedPointer); - TESTCASE_AUTO(TestErrorCallingConstructor); - TESTCASE_AUTO(TestLRUCache); - TESTCASE_AUTO(TestLRUCacheError); - TESTCASE_AUTO_END; -} - -void LRUCacheTest::TestSharedPointer() { - UErrorCode status = U_ZERO_ERROR; - LRUCacheForTesting cache(3, "little", status); - const CopyOnWriteForTesting* ptr = NULL; - cache.get("boo", ptr, status); - verifySharedPointer(ptr, "boo", "little"); - const CopyOnWriteForTesting* ptrCopy = ptr; - ptrCopy->addRef(); - { - const CopyOnWriteForTesting* ptrCopy2(ptrCopy); - ptrCopy2->addRef(); - verifyReferences(ptr, 4, 1, 2); - ptrCopy2->removeRef(); - } - - verifyReferences(ptr, 3, 1, 2); - CopyOnWriteForTesting *wPtrCopy = SharedObject::copyOnWrite(ptrCopy); - *wPtrCopy->localeNamePtr.readWrite() = UnicodeString("hi there"); - *wPtrCopy->formatStrPtr.readWrite() = UnicodeString("see you"); - verifyReferences(ptr, 2, 1, 2); - verifyReferences(ptrCopy, 1, 1, 1); - verifySharedPointer(ptr, "boo", "little"); - verifySharedPointer(ptrCopy, "hi there", "see you"); - ptrCopy->removeRef(); - ptr->removeRef(); -} - -void LRUCacheTest::TestErrorCallingConstructor() { - UErrorCode status = U_MEMORY_ALLOCATION_ERROR; - LRUCacheForTesting cache(3, "little", status); -} - -void LRUCacheTest::TestLRUCache() { - UErrorCode status = U_ZERO_ERROR; - LRUCacheForTesting cache(3, "little", status); - const CopyOnWriteForTesting* ptr1 = NULL; - const CopyOnWriteForTesting* ptr2 = NULL; - const CopyOnWriteForTesting* ptr3 = NULL; - const CopyOnWriteForTesting* ptr4 = NULL; - const CopyOnWriteForTesting* ptr5 = NULL; - cache.get("foo", ptr1, status); - cache.get("bar", ptr2, status); - cache.get("baz", ptr3, status); - verifySharedPointer(ptr1, "foo", "little"); - verifySharedPointer(ptr2, "bar", "little"); - verifySharedPointer(ptr3, "baz", "little"); - - // Cache holds a reference to returned data which explains the 2s - // Note the '4'. each cached data has a reference to "little" and the - // cache itself also has a reference to "little" - verifyReferences(ptr1, 2, 1, 4); - verifyReferences(ptr2, 2, 1, 4); - verifyReferences(ptr3, 2, 1, 4); - - // (Most recent) "baz", "bar", "foo" (Least Recent) - // Cache is now full but thanks to shared pointers we can still evict. - cache.get("full", ptr4, status); - verifySharedPointer(ptr4, "full", "little"); - - verifyReferences(ptr4, 2, 1, 5); - - // (Most Recent) "full" "baz", "bar" (Least Recent) - cache.get("baz", ptr5, status); - verifySharedPointer(ptr5, "baz", "little"); - // ptr5, ptr3, and cache have baz data - verifyReferences(ptr5, 3, 1, 5); - - // This should delete foo data since it got evicted from cache. - ptr1->removeRef(); - ptr1 = NULL; - // Reference count for little drops to 4 because foo data was deleted. - verifyReferences(ptr5, 3, 1, 4); - - // (Most Recent) "baz" "full" "bar" (Least Recent) - cache.get("baz", ptr5, status); - verifySharedPointer(ptr5, "baz", "little"); - verifyReferences(ptr5, 3, 1, 4); - - // (Most Recent) "baz", "full", "bar" (Least Recent) - // ptr3, ptr5 -> "baz" ptr4 -> "full" ptr2 -> "bar" - if (!cache.contains("baz") || !cache.contains("full") || !cache.contains("bar") || cache.contains("foo")) { - errln("Unexpected keys in cache."); - } - cache.get("new1", ptr5, status); - verifySharedPointer(ptr5, "new1", "little"); - verifyReferences(ptr5, 2, 1, 5); - - // Since bar was evicted, clearing its pointer should delete its data. - // Notice that the reference count to 'little' dropped from 5 to 4. - ptr2->removeRef(); - ptr2 = NULL; - verifyReferences(ptr5, 2, 1, 4); - if (cache.contains("bar") || !cache.contains("full")) { - errln("Unexpected 'bar' in cache."); - } - - // (Most Recent) "new1", "baz", "full" (Least Recent) - // ptr3 -> "baz" ptr4 -> "full" ptr5 -> "new1" - cache.get("new2", ptr5, status); - verifySharedPointer(ptr5, "new2", "little"); - verifyReferences(ptr5, 2, 1, 5); - - // since "full" was evicted, clearing its pointer should delete its data. - ptr4->removeRef(); - ptr4 = NULL; - verifyReferences(ptr5, 2, 1, 4); - if (cache.contains("full") || !cache.contains("baz")) { - errln("Unexpected 'full' in cache."); - } - - // (Most Recent) "new2", "new1", "baz" (Least Recent) - // ptr3 -> "baz" ptr5 -> "new2" - cache.get("new3", ptr5, status); - verifySharedPointer(ptr5, "new3", "little"); - verifyReferences(ptr5, 2, 1, 5); - - // since "baz" was evicted, clearing its pointer should delete its data. - ptr3->removeRef(); - ptr3 = NULL; - verifyReferences(ptr5, 2, 1, 4); - if (cache.contains("baz") || !cache.contains("new3")) { - errln("Unexpected 'baz' in cache."); - } - SharedObject::clearPtr(ptr1); - SharedObject::clearPtr(ptr2); - SharedObject::clearPtr(ptr3); - SharedObject::clearPtr(ptr4); - SharedObject::clearPtr(ptr5); -} - -void LRUCacheTest::TestLRUCacheError() { - UErrorCode status = U_ZERO_ERROR; - LRUCacheForTesting cache(3, "little", status); - const CopyOnWriteForTesting *ptr1; - cache.get("error", ptr1, status); - if (status != U_ILLEGAL_ARGUMENT_ERROR) { - errln("Expected an error."); - } -} - -void LRUCacheTest::verifySharedPointer( - const CopyOnWriteForTesting* ptr, - const UnicodeString& name, - const UnicodeString& format) { - const UnicodeString *strPtr = ptr->localeNamePtr.readOnly(); - verifyString(name, *strPtr); - strPtr = ptr->formatStrPtr.readOnly(); - verifyString(format, *strPtr); -} - -void LRUCacheTest::verifyString(const UnicodeString &expected, const UnicodeString &actual) { - if (expected != actual) { - errln(UnicodeString("Expected '") + expected + "', got '"+ actual+"'"); - } -} - -void LRUCacheTest::verifyReferences(const CopyOnWriteForTesting* ptr, int32_t count, int32_t nameCount, int32_t formatCount) { - int32_t actual = ptr->getRefCount(); - if (count != actual) { - errln("Main reference count wrong: Expected %d, got %d", count, actual); - } - actual = ptr->localeNamePtr.count(); - if (nameCount != actual) { - errln("name reference count wrong: Expected %d, got %d", nameCount, actual); - } - actual = ptr->formatStrPtr.count(); - if (formatCount != actual) { - errln("format reference count wrong: Expected %d, got %d", formatCount, actual); - } -} - -extern IntlTest *createLRUCacheTest() { - return new LRUCacheTest(); -}