public Option <TWeakOwningKey> GetPossibleWeakKeyFromValue(TContained contained) { lock (mLock) { foreach (var wrn in ContainedToKeyAndNeutralizeKillShot.GetValueIfPresent(contained).ToEnumerable()) { if (wrn.Item1.TryGetTarget(out var possible)) { return(Some(possible)); } } return(None <TWeakOwningKey>()); } }
private Either <TWeakOwningKey, T> AddUtility <T>(TContained contained, Func <TWeakOwningKey> buildNewResourceKey, Func <TContained, TWeakOwningKey, T> toReturnIfAlreadyExists) { lock (mLock) { foreach (var wrn in ContainedToKeyAndNeutralizeKillShot.GetValueIfPresent(contained).ToEnumerable()) { if (wrn.Item1.TryGetTarget(out var possible)) { return(Either <TWeakOwningKey, T> .FromRight(toReturnIfAlreadyExists(contained, possible))); } else { // ** IMPORTANT ** - we failed to get the weak back - the weak-key is gone, ergo while there is a contained object here, it's to be considered defunct. // However, theoretically, an outstanding killshot could be hanging on this lock to remove ContainedToKey. wrn.Item2(); // don't want it to come back and kill the one we will add ContainedToKeyAndNeutralizeKillShot.Remove(contained); // remove it ourself, now that noone else will // Will fall through and rebuild the entry. } } // build it. var resourceKey = buildNewResourceKey(); var(newKeyHolder, neutralizeKillShot) = NewKeyHolderAndNeutralizeKillShot(mLock, ContainedToKeyAndNeutralizeKillShot, contained); KeyToContained.Add( resourceKey, Tuple.Create( contained, newKeyHolder)); ContainedToKeyAndNeutralizeKillShot.Add(contained, Tuple.Create(new WeakReference <TWeakOwningKey>(resourceKey), neutralizeKillShot)); return(Either <TWeakOwningKey, T> .FromLeft(resourceKey)); } }