/// <summary> /// Either retrieve an existing part instance with the specified sharing id, or /// create and share a new part instance using <paramref name="creator"/> within /// <paramref name="operation"/>. /// </summary> /// <param name="sharingId">Sharing id for the part in question.</param> /// <param name="operation">Operation in which to activate a new part instance if necessary.</param> /// <param name="creator">Activator that can activate a new part instance if necessary.</param> /// <returns>The part instance corresponding to <paramref name="sharingId"/> within this lifetime context.</returns> /// <remarks>This method is lock-free if the part instance already exists. If the part instance must be created, /// a lock will be taken that will serialize other writes via this method (concurrent reads will continue to /// be safe and lock-free). It is important that the composition, and thus lock acquisition, is strictly /// leaf-to-root in the lifetime tree.</remarks> public object GetOrCreate(int sharingId, CompositionOperation operation, CompositeActivator creator) { object result; if (_sharedPartInstances != null && _sharedPartInstances.TryGetValue(sharingId, out result)) { return(result); } // Remains locked for the rest of the operation. operation.EnterSharingLock(_sharingLock); if (_sharedPartInstances == null) { _sharedPartInstances = new SmallSparseInitonlyArray(); _instancesUndergoingInitialization = new SmallSparseInitonlyArray(); } else if (_sharedPartInstances.TryGetValue(sharingId, out result)) { return(result); } // Already being initialized _on the same thread_. if (_instancesUndergoingInitialization.TryGetValue(sharingId, out result)) { return(result); } result = creator(this, operation); _instancesUndergoingInitialization.Add(sharingId, result); operation.AddPostCompositionAction(() => { _sharedPartInstances.Add(sharingId, result); }); return(result); }
public bool TryGetValue(int index, out object value) { if (_elements == null) { value = null; return(false); } var elementIndex = index & ElementIndexMask; var e = _elements[elementIndex]; if (e != null && e.Index == index) { value = e.Value; return(true); } for (int offset = 1; offset <= LocalOffsetMax; ++offset) { e = _elements[(index + offset) & ElementIndexMask]; if (e == null) { value = null; return(false); } if (e.Index == index) { value = e.Value; return(true); } } if (_overflow != null) { return(_overflow.TryGetValue(index, out value)); } value = null; return(false); }