private void SetConstructor(ConstructorCacheKey cacheKey, ConstructorCacheValue previousCacheValue, ConstructorInfo constructorInfo) { // Currently I choose last-win strategy but maybe other should be used _constructorCacheLock.PerformWrite(() => { ConstructorCacheValue storedValue; if (!_constructorCache.TryGetValue(cacheKey, out storedValue)) { storedValue = ConstructorCacheValue.First(); } if (storedValue.Version == previousCacheValue.Version) { // Log.Debug("Everything is fine"); } else if (storedValue.Version > previousCacheValue.Version) { Log.Debug("Data in cache have been changed between read & write."); } else { // TODO: Maybe exception should be thrown Log.Debug("Something strange have happend. Deep log analyze required."); } // I'm not sure storedValue or previousCacheValue should be passed in here var cacheValue = ConstructorCacheValue.Next(storedValue, constructorInfo); _constructorCache[cacheKey] = cacheValue; }); }
private ConstructorCacheValue GetConstructor(ConstructorCacheKey cacheKey) { return(_constructorCacheLock.PerformRead(() => { ConstructorCacheValue result; if (_constructorCache.TryGetValue(cacheKey, out result)) { return result; } return ConstructorCacheValue.First(); })); }
/// <summary> /// Clears the cache of all constructors. /// <para /> /// This call is normally not necessary since the type factory should keep an eye on the /// <see cref="IServiceLocator.TypeRegistered"/> event to invalidate the cache. /// </summary> public void ClearCache() { // Note that we don't clear the constructor metadata cache, constructors on types normally don't change during an // application lifetime // Clear cache isn't really that important, it's better to prevent deadlocks. How can a deadlock occur? If thread x is creating // a type and loads an assembly, but thread y is also loading an assembly. Thread x will lock because it's creating the type, // thread y will lock because it wants to clear the cache because new types were added. In that case ignore clearing the cache // Edit: Probability of loading assembly inside of lock have been drastically reduced so comment above probably isn't relevant _constructorCacheLock.PerformWrite(() => { var array = _constructorCache.ToArray(); foreach (var keyValuePair in array) { _constructorCache[keyValuePair.Key] = ConstructorCacheValue.Next(keyValuePair.Value, null); } }); // This log entry makes sence in optimistic lock scenarios Log.Debug("Cleared type constructor cache"); }
/// <summary> /// Creates entry that replaces previous entry in cache for key. /// </summary> /// <param name="previousValue">Previously used constructor.</param> /// <param name="constructorInfo">Creates first entry in cache for key.</param> /// <returns></returns> public static ConstructorCacheValue Next(ConstructorCacheValue previousValue, ConstructorInfo constructorInfo) { return(new ConstructorCacheValue(constructorInfo, previousValue.Version + 1)); }