diff options
| author | dskor <[email protected]> | 2025-10-16 01:40:10 +0300 | 
|---|---|---|
| committer | dskor <[email protected]> | 2025-10-16 02:22:15 +0300 | 
| commit | 8d275bde2bd67470dccbba997208810b4280d8f0 (patch) | |
| tree | a8fdd96862e2f9ee45f76dd059714983f1ae55b3 /library/cpp/cache | |
| parent | 52bb9813716cd4308702d44d69fb3a448500f50f (diff) | |
TWriteGuard on GetOrNull for ThreadSaveCache with promotion
Find может делать Promote, который мутирует List ( LRUList например: <https://nda.ya.ru/t/fFSNn0ML7LRudF> )
commit_hash:dca1db67d45c7faca51cc1251cbe155c7857e362
Diffstat (limited to 'library/cpp/cache')
| -rw-r--r-- | library/cpp/cache/thread_safe_cache.h | 17 | ||||
| -rw-r--r-- | library/cpp/cache/ut/cache_ut.cpp | 51 | 
2 files changed, 63 insertions, 5 deletions
diff --git a/library/cpp/cache/thread_safe_cache.h b/library/cpp/cache/thread_safe_cache.h index b4bd4deedf2..045bea0c8c3 100644 --- a/library/cpp/cache/thread_safe_cache.h +++ b/library/cpp/cache/thread_safe_cache.h @@ -52,12 +52,19 @@ namespace NPrivate {          const TPtr GetOrNull(TArgs... args) {              Key key = Callbacks.GetKey(args...); -            TReadGuard r(Mutex); -            auto iter = Cache.Find(key); -            if (iter == Cache.End()) { -                return nullptr; +            switch (GettersPromotionPolicy) { +                case EGettersPromotionPolicy::Promoted: { +                    TWriteGuard r(Mutex); +                    if (auto iter = Cache.Find(key); iter != Cache.End()) +                        return iter.Value(); +                } +                case EGettersPromotionPolicy::Unpromoted: { +                    TReadGuard r(Mutex); +                    if (auto iter = Cache.Find(key); iter != Cache.End()) +                        return iter.Value(); +                }              } -            return iter.Value(); +            return nullptr;          }          const TPtr Get(TArgs... args) const { diff --git a/library/cpp/cache/ut/cache_ut.cpp b/library/cpp/cache/ut/cache_ut.cpp index 16f29b29d1f..c4c829cdb7d 100644 --- a/library/cpp/cache/ut/cache_ut.cpp +++ b/library/cpp/cache/ut/cache_ut.cpp @@ -2,6 +2,10 @@  #include <library/cpp/cache/thread_safe_cache.h>  #include <library/cpp/testing/unittest/registar.h> +#include <util/thread/pool.h> +#include <util/string/cast.h> +#include <util/random/random.h> +  struct TStrokaWeighter {      static size_t Weight(const TString& s) {          return s.size(); @@ -536,6 +540,53 @@ Y_UNIT_TEST_SUITE(TThreadSafeCacheTest) {      }  } +Y_UNIT_TEST_SUITE(TThreadSafeLRUCacheMultiThreadTest) { +    typedef TThreadSafeLRUCache<ui32, TString, ui32> TCache; + +    class TSimpleCallbacks: public TCache::ICallbacks { +    public: +        TKey GetKey(ui32 i) const override { +            return i; +        } +        TValue* CreateObject(ui32 i) const override { +            Y_UNUSED(i); +            return nullptr; +        } +    }; + +    Y_UNIT_TEST(GetOrNullMultiThreadTest) { +        const size_t poolSize = 8; +        const size_t passCnt = 128; +        const size_t tasksCnt = 128; + +        TRWMutex lock; +        TThreadPool pool; +        TSimpleCallbacks callbacks; +        TCache cache(callbacks, poolSize); + +        for (size_t i = 0; i < poolSize; ++i) { +            cache.Insert(i, MakeAtomicShared<TString>(ToString(i))); +        } + +        pool.Start(poolSize); +        { +            TWriteGuard wGruard(lock); +            for (size_t i = 0; i < tasksCnt; ++i) { +                pool.SafeAddFunc([&lock, &cache]() { +                    TReadGuard rGuard(lock); +                    for (size_t j = 0; j < passCnt; ++j) { +                        UNIT_ASSERT(cache.GetOrNull(RandomNumber<size_t>(poolSize)) != nullptr); +                    } +                }); +            } +        } // start race +        pool.Stop(); +        for (size_t i = 0; i < cache.Size(); ++i) { +            UNIT_ASSERT(cache.GetOrNull(i) != nullptr); +        } +    } +} +  Y_UNIT_TEST_SUITE(TThreadSafeCacheUnsafeTest) {      typedef TThreadSafeCache<ui32, TString, ui32> TCache;  | 
