public virtual double Remove(E key) { AtomicDouble atomic = map[key]; if (atomic == null) { return(defaultReturnValue); } for (; ;) { double oldValue = atomic.Get(); if (oldValue == 0.0 || atomic.CompareAndSet(oldValue, 0.0)) { // only remove after setting to zero, to avoid concurrent updates Sharpen.Collections.Remove(map, key, atomic); // succeed even if the remove fails, since the value was already adjusted totalCount.AddAndGet(-1.0 * oldValue); return(oldValue); } } }
public virtual double LogIncrementCount(E key, double value) { // TODO Inspired by Guava.AtomicLongMap // Modify for our use? for (; ;) { AtomicDouble atomic = map[key]; if (atomic == null) { atomic = map.PutIfAbsent(key, new AtomicDouble(value)); if (atomic == null) { totalCount.AddAndGet(value); return(value); } } for (; ;) { double oldValue = atomic.Get(); if (oldValue == 0.0) { // don't compareAndSet a zero if (map.Replace(key, atomic, new AtomicDouble(value))) { totalCount.AddAndGet(value); return(value); } goto outer_continue; } double newValue = SloppyMath.LogAdd(oldValue, value); if (atomic.CompareAndSet(oldValue, newValue)) { totalCount.AddAndGet(value); return(newValue); } } outer_continue :; } outer_break :; }
public virtual double GetCount(object key) { AtomicDouble v = map[key]; return(v == null ? defaultReturnValue : v.Get()); }
public ConcurrentHashCounter(int initialCapacity) { map = new ConcurrentHashMap <E, AtomicDouble>(initialCapacity); totalCount = new AtomicDouble(); }