T IContextCache.GetOrAddContext <T>(ContextFactory <T> contextFactory) { try { IContextValue <T> context = null; IContextCollection currentCollection; do { T existingValue; if (_collection.TryGetContext(out existingValue)) { return(existingValue); } IContextValue <T> contextProperty = context ?? (context = new ContextValue <T>(contextFactory())); currentCollection = Volatile.Read(ref _collection); Interlocked.CompareExchange(ref _collection, currentCollection.Add(contextProperty), currentCollection); } while (currentCollection == Volatile.Read(ref _collection)); return(context.Value); } catch (Exception exception) { throw new ContextFactoryException($"The payload factory faulted: {TypeCache<T>.ShortName}", exception); } }
T IContextCache.AddOrUpdateContext <T>(ContextFactory <T> addFactory, UpdateContextFactory <T> updateFactory) { try { T previousValue = null; IContextValue <T> context = null; IContextCollection currentCollection; do { T existingValue; if (_collection.TryGetContext(out existingValue)) { if (context == null || previousValue != existingValue) { context = new ContextValue <T>(updateFactory(existingValue)); } previousValue = existingValue; currentCollection = Volatile.Read(ref _collection); Interlocked.CompareExchange(ref _collection, currentCollection.Add(context), currentCollection); } else { if (context == null) { context = new ContextValue <T>(addFactory()); } currentCollection = Volatile.Read(ref _collection); Interlocked.CompareExchange(ref _collection, currentCollection.Add(context), currentCollection); } } while (currentCollection == Volatile.Read(ref _collection)); return(context.Value); } catch (Exception exception) { throw new ContextFactoryException($"The payload factory faulted: {TypeCache<T>.ShortName}", exception); } }