diff --git a/uppsrc/Core/Other.h b/uppsrc/Core/Other.h index dc0aac10f..01180a4db 100644 --- a/uppsrc/Core/Other.h +++ b/uppsrc/Core/Other.h @@ -258,7 +258,9 @@ public: template int Remove(P predicate); template bool RemoveOne(P predicate); - T& Get(const Maker& m); + template + T& Get(const Maker& m, B before_make, A after_make); + T& Get(const Maker& m) { return Get(m, []{}, []{}); } void Clear(); diff --git a/uppsrc/Core/Other.hpp b/uppsrc/Core/Other.hpp index 25d8976f5..3369d847d 100644 --- a/uppsrc/Core/Other.hpp +++ b/uppsrc/Core/Other.hpp @@ -177,7 +177,8 @@ void LRUCache::ClearCounters() } template -T& LRUCache::Get(const Maker& m) +template +T& LRUCache::Get(const Maker& m, B before_make, A after_make) { Key k; k.key = m.Key(); @@ -185,7 +186,9 @@ T& LRUCache::Get(const Maker& m) int q = key.Find(k); if(q < 0) { One val; + before_make(); int sz = m.Make(val.Create()); + after_make(); q = key.Put(k); Item& t = data.At(q); t.data = pick(val); diff --git a/uppsrc/Core/ValueCache.cpp b/uppsrc/Core/ValueCache.cpp index ab3c88962..ba1a0f983 100644 --- a/uppsrc/Core/ValueCache.cpp +++ b/uppsrc/Core/ValueCache.cpp @@ -64,7 +64,7 @@ Value MakeValue(ValueMaker& m) { Mutex::Lock __(ValueCacheMutex); LLOG("MakeValue cache size before make: " << TheValueCache().GetSize()); - Value v = TheValueCache().Get(m); + Value v = TheValueCache().Get(m, [] { ValueCacheMutex.Leave(); }, [] { ValueCacheMutex.Enter(); }); LLOG("MakeValue cache size after make: " << TheValueCache().GetSize()); ShrinkValueCache(); LLOG("-------------"); diff --git a/uppsrc/Core/src.tpp/LRUCache_en-us.tpp b/uppsrc/Core/src.tpp/LRUCache_en-us.tpp index 303bdf53a..6ba71e5fe 100644 --- a/uppsrc/Core/src.tpp/LRUCache_en-us.tpp +++ b/uppsrc/Core/src.tpp/LRUCache_en-us.tpp @@ -117,9 +117,19 @@ items to least recently used. Returns true if item was found and removed.&] [s3;%% &] [s4; &] +[s5;:Upp`:`:LRUCache`:`:Get`(const Upp`:`:LRUCache`:`:Maker`&`,B`,A`): [@(0.0.255) temp +late] T[@(0.0.255) `&] [* Get]([@(0.0.255) const] Maker[@(0.0.255) `&] +[*@3 m], B [*@3 before`_make], A [*@3 after`_make])&] +[s2;%% Retrieves data from the cache or creates them if needed. Required +data and method to create them is provided by [%-*@3 m]. If data +needs to be created, [%-*@3 before`_make] is called before call +to Maker`::Make and [%-*@3 after`_make] when it is finished.&] +[s3; &] +[s4; &] [s5;:LRUCache`:`:Get`(const LRUCache`:`:Maker`&`): [*@4 T][@(0.0.255) `&]_[* Get]([@(0.0.255) c onst]_[_^LRUCache`:`:Maker^ Maker][@(0.0.255) `&]_[*@3 m])&] -[s2;%% Retrieves data from the cache or creates them if needed [%-*@3 m].&] +[s2;%% Retrieves data from the cache or creates them if needed. Required +data and method to create them is provided by [%-*@3 m].&] [s3;%% &] [s4; &] [s5;:LRUCache`:`:Clear`(`): [@(0.0.255) void]_[* Clear]()&] diff --git a/uppsrc/Core/src.tpp/ValueCache_en-us.tpp b/uppsrc/Core/src.tpp/ValueCache_en-us.tpp index 1f46fc345..06fe0c1cb 100644 --- a/uppsrc/Core/src.tpp/ValueCache_en-us.tpp +++ b/uppsrc/Core/src.tpp/ValueCache_en-us.tpp @@ -24,7 +24,7 @@ alueMaker][@(0.0.255) `&]_[*@3 m])&] derived from ValueMaker, which is class with two virtual methods:&] [s2; &] [s2; virtual String [* Key]() const;&] -[s2; virtual int [* Make](T`& object) const;&] +[s2; virtual int [* Make](Value`& object) const;&] [s2; &] [s2; [* Key] should return unique identifier for Value requested with ValueMaker derived class. Note that the type of ValueMaker derived @@ -34,7 +34,10 @@ the corresponding Value and returns the approximate memory consumption needed to store that Value. [* MakeValue] first checks whether Value corresponding to given ValueMaker and Key are in the cache, if yes then it returns Value from the cache, otherwise calls -ValueMaker`::Make to obtain the Value and stores it to the cache.&] +ValueMaker`::Make to obtain the Value and stores it to the cache. +Note that this function allows full reentrancy (from various +threads as well as recursive calls (through Make method) in single +thread&] [s3; &] [s4;%- &] [s5;:Upp`:`:IsValueCacheActive`(`):%- [@(0.0.255) bool]_[* IsValueCacheActive]()&]