T IPayloadCache.GetOrAddPayload <T>(PayloadFactory <T> payloadFactory) { try { IPayloadValue <T> payload = null; IPayloadCollection currentCollection; do { if (_collection.TryGetPayload(out T existingValue)) { return(existingValue); } IPayloadValue <T> contextProperty = payload ?? (payload = new PayloadValue <T>(payloadFactory())); currentCollection = Volatile.Read(ref _collection); Interlocked.CompareExchange(ref _collection, currentCollection.Add(contextProperty), currentCollection); }while (currentCollection == Volatile.Read(ref _collection)); return(payload.Value); } catch (Exception exception) { throw new PayloadFactoryException($"The payload factory faulted: {TypeCache<T>.ShortName}", exception); } }
T IPayloadCache.AddOrUpdatePayload <T>(PayloadFactory <T> addFactory, UpdatePayloadFactory <T> updateFactory) { try { T previousValue = null; IPayloadValue <T> context = null; IPayloadCollection currentCollection; do { if (_collection.TryGetPayload(out T existingValue)) { if (context == null || previousValue != existingValue) { context = new PayloadValue <T>(updateFactory(existingValue)); } previousValue = existingValue; currentCollection = Volatile.Read(ref _collection); Interlocked.CompareExchange(ref _collection, currentCollection.Add(context), currentCollection); } else { if (context == null) { context = new PayloadValue <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 PayloadFactoryException($"The payload factory faulted: {TypeCache<T>.ShortName}", exception); } }