internal AsyncWaitHandle InitiateLockResolution(long instanceVersion, ref InstanceHandleReference reference, ref List <InstanceHandleReference> handlesPendingResolution) { AsyncWaitHandle markerWaitHandle; Fx.AssertAndThrow(!(reference is LockResolutionMarker), "InitiateLockResolution already called."); lock (this.HandlesLock) { InstanceHandleReference reference2 = reference; LockResolutionMarker handleRef = null; try { InstanceHandle handle; if (this.BoundHandles.TryGetValue(reference.InstanceHandle.Id, out handle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(handle, reference.InstanceHandle), "InstanceStore lock state is not correct in InitiateLockResolution."); if ((handle.Version <= 0L) || (instanceVersion <= 0L)) { if ((handle.Version != 0L) || (instanceVersion != 0L)) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidLockToken)); } reference.InstanceHandle.ConflictingHandle = handle; return(null); } if (handle.Version >= instanceVersion) { reference.InstanceHandle.ConflictingHandle = handle; return(null); } } handleRef = new LockResolutionMarker(reference.InstanceHandle, instanceVersion); this.EnqueueReference(handleRef); reference = handleRef; markerWaitHandle = handleRef.MarkerWaitHandle; } finally { if (!object.ReferenceEquals(handleRef, reference)) { this.CancelReference(ref reference, ref handlesPendingResolution); if (handleRef != null) { reference2 = handleRef; this.CancelReference(ref reference2, ref handlesPendingResolution); } } else { this.CancelReference(ref reference2, ref handlesPendingResolution); } } } return(markerWaitHandle); }
private void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args) { try { this.CheckAndWork(args.LoadedAssembly); } catch { Fx.AssertAndFailFast("OnAssemblyLoad should not throw exception"); throw; } }
// Must be called with HandlesLock held. // This is called when a reference becomes the oldest in-progress reference for an instance. This triggers the end of resolution for markers. // Returns false if the resolution failed, meaning that the marker can be removed. bool CheckOldestReference(InstanceHandleReference handleRef, ref List <InstanceHandleReference> handlesPendingResolution) { LockResolutionMarker marker = handleRef as LockResolutionMarker; if (marker == null || marker.IsComplete) { return(true); } bool returnValue = true; try { InstanceHandle existingHandle; if (BoundHandles.TryGetValue(marker.InstanceHandle.Id, out existingHandle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(existingHandle, marker.InstanceHandle), "InstanceStore lock state is not correct in CheckOldestReference."); if (existingHandle.Version <= 0 || marker.InstanceVersion <= 0) { if (existingHandle.Version != 0 || marker.InstanceVersion != 0) { marker.Reason = new InvalidOperationException(SRCore.InvalidLockToken); returnValue = false; } else { marker.ConflictingHandle = existingHandle; returnValue = false; } } else if (existingHandle.Version >= marker.InstanceVersion) { marker.ConflictingHandle = existingHandle; returnValue = false; } } // No other handles have committed a bind to this or a higher version! We are ok to do so, but it is still not committed, so we stay in queue. return(returnValue); } finally { marker.NotifyMarkerComplete(returnValue); if (handlesPendingResolution == null) { handlesPendingResolution = new List <InstanceHandleReference>(1); } handlesPendingResolution.Add(marker); } }
private void ScheduleWorkItem(WorkItem item) { lock (this.thisLock) { Fx.AssertAndFailFast(this.currentWorkItem == null, "There cannot be more than 1 work item at a given time"); this.currentWorkItem = item; if (this.queueWaiter != null) { // Since we don't know which thread this is being called from we just set // the waiter directly rather than doing our SetWaiter cleanup. this.queueWaiter.Set(); } } }
internal bool TryCompleteBind(ref InstanceHandleReference reference, ref List <InstanceHandleReference> handlesPendingResolution, out InstanceHandle handleToFree) { bool flag2; handleToFree = null; lock (this.HandlesLock) { try { InstanceHandle handle; if (this.BoundHandles.TryGetValue(reference.InstanceHandle.Id, out handle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(handle, reference.InstanceHandle), "InstanceStore lock state is not correct."); if ((handle.Version <= 0L) || (reference.InstanceHandle.Version <= 0L)) { if ((handle.Version != 0L) || (reference.InstanceHandle.Version != 0L)) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidLockToken)); } reference.InstanceHandle.ConflictingHandle = handle; return(false); } if (handle.Version > reference.InstanceHandle.Version) { reference.InstanceHandle.ConflictingHandle = handle; return(false); } if (handle.Version < reference.InstanceHandle.Version) { handle.ConflictingHandle = reference.InstanceHandle; handleToFree = handle; this.BoundHandles[reference.InstanceHandle.Id] = reference.InstanceHandle; return(true); } if (handle.Version == reference.InstanceHandle.Version) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InstanceStoreBoundSameVersionTwice)); } throw Fx.AssertAndThrow("All cases covered above."); } this.BoundHandles.Add(reference.InstanceHandle.Id, reference.InstanceHandle); flag2 = true; } finally { this.CancelReference(ref reference, ref handlesPendingResolution); } } return(flag2); }
private bool CheckOldestReference(InstanceHandleReference handleRef, ref List <InstanceHandleReference> handlesPendingResolution) { bool flag2; LockResolutionMarker item = handleRef as LockResolutionMarker; if ((item == null) || item.IsComplete) { return(true); } bool success = true; try { InstanceHandle handle; if (this.BoundHandles.TryGetValue(item.InstanceHandle.Id, out handle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(handle, item.InstanceHandle), "InstanceStore lock state is not correct in CheckOldestReference."); if ((handle.Version <= 0L) || (item.InstanceVersion <= 0L)) { if ((handle.Version != 0L) || (item.InstanceVersion != 0L)) { item.Reason = new InvalidOperationException(SRCore.InvalidLockToken); success = false; } else { item.ConflictingHandle = handle; success = false; } } else if (handle.Version >= item.InstanceVersion) { item.ConflictingHandle = handle; success = false; } } flag2 = success; } finally { item.NotifyMarkerComplete(success); if (handlesPendingResolution == null) { handlesPendingResolution = new List <InstanceHandleReference>(1); } handlesPendingResolution.Add(item); } return(flag2); }
// Since tracking can go async this may or may not be called directly under a call to // workItem.Invoke. Also, the scheduler may call OnNotifyPaused or // OnNotifyUnhandledException from any random thread if runtime goes async (post-work // item tracking, AsyncCodeActivity). public void OnInvokeCompleted() { Fx.AssertAndFailFast(this.currentWorkItem == null, "There can be no pending work items when complete"); this.IsInvokeCompleted = true; lock (this.thisLock) { if (this.queueWaiter != null) { // Since we don't know which thread this is being called from we just set // the waiter directly rather than doing our SetWaiter cleanup. this.queueWaiter.Set(); } } }
// This is called if we found an existing lock. This handle doesn't own the lock, but it could claim it, if it can prove // that no other live handle owns it. If this returns non-null, the outcome will be available later on the // InstanceHandleReference once the AsyncWaitHandle completes. (Null indicates a conflict with another handle.) // // The instanceVersion reported here was read under the transaction, but not changed. Either it was already committed, or it was written under // this transaction in a prior command on a different handle. Due to the latter case, we treat it as dirty - we do not publish it or take // any visible action (such as dooming handles) based on its value. internal AsyncWaitHandle InitiateLockResolution(long instanceVersion, ref InstanceHandleReference reference, ref List <InstanceHandleReference> handlesPendingResolution) { Fx.Assert(reference != null, "Bind wasn't registered - RegisterStartBind must be called."); Fx.Assert(reference.InstanceHandle != null, "Cannot cancel and complete a bind."); Fx.Assert(reference.InstanceHandle.Id != Guid.Empty, "Must be bound to an instance already."); Fx.AssertAndThrow(!(reference is LockResolutionMarker), "InitiateLockResolution already called."); lock (HandlesLock) { InstanceHandleReference cancelReference = reference; LockResolutionMarker markerReference = null; try { InstanceHandle existingHandle; if (BoundHandles.TryGetValue(reference.InstanceHandle.Id, out existingHandle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(existingHandle, reference.InstanceHandle), "InstanceStore lock state is not correct in InitiateLockResolution."); if (existingHandle.Version <= 0 || instanceVersion <= 0) { if (existingHandle.Version != 0 || instanceVersion != 0) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidLockToken)); } reference.InstanceHandle.ConflictingHandle = existingHandle; return(null); } if (existingHandle.Version >= instanceVersion) { reference.InstanceHandle.ConflictingHandle = existingHandle; return(null); } } // Put a marker in the InProgressHandles. If it makes it through, and there's still no conflicting handle, // then the lock can be claimed at this version. Only currently in-progress bindings have a chance of // staking a stronger claim to the lock version (if the store actually acquired the lock for the handle). markerReference = new LockResolutionMarker(reference.InstanceHandle, instanceVersion); EnqueueReference(markerReference); reference = markerReference; Fx.Assert(markerReference.MarkerWaitHandle != null, "Null MarkerWaitHandle?"); return(markerReference.MarkerWaitHandle); } finally { if (!object.ReferenceEquals(markerReference, reference)) { CancelReference(ref reference, ref handlesPendingResolution); if (markerReference != null) { cancelReference = markerReference; CancelReference(ref cancelReference, ref handlesPendingResolution); } } else { CancelReference(ref cancelReference, ref handlesPendingResolution); } } } }
// This happens only when the transaction under which the handle was bound is committed. internal bool TryCompleteBind(ref InstanceHandleReference reference, ref List <InstanceHandleReference> handlesPendingResolution, out InstanceHandle handleToFree) { Fx.Assert(reference != null, "Bind wasn't registered - RegisterStartBind must be called."); Fx.Assert(reference.InstanceHandle != null, "Cannot cancel and complete a bind."); Fx.Assert(reference.InstanceHandle.Version != -1, "Handle state must be set first."); Fx.Assert(object.ReferenceEquals(this, reference.InstanceHandle.Owner), "TryCompleteBind called on the wrong owner for a handle."); Fx.Assert(!(reference is LockResolutionMarker) || ((LockResolutionMarker)reference).NonConflicting, "How did a Version get set if we're still resolving."); handleToFree = null; lock (HandlesLock) { try { InstanceHandle existingHandle; if (BoundHandles.TryGetValue(reference.InstanceHandle.Id, out existingHandle)) { Fx.AssertAndFailFast(!object.ReferenceEquals(existingHandle, reference.InstanceHandle), "InstanceStore lock state is not correct."); if (existingHandle.Version <= 0 || reference.InstanceHandle.Version <= 0) { if (existingHandle.Version != 0 || reference.InstanceHandle.Version != 0) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InvalidLockToken)); } reference.InstanceHandle.ConflictingHandle = existingHandle; return(false); } if (existingHandle.Version > reference.InstanceHandle.Version) { reference.InstanceHandle.ConflictingHandle = existingHandle; return(false); } if (existingHandle.Version < reference.InstanceHandle.Version) { existingHandle.ConflictingHandle = reference.InstanceHandle; handleToFree = existingHandle; BoundHandles[reference.InstanceHandle.Id] = reference.InstanceHandle; return(true); } if (existingHandle.Version == reference.InstanceHandle.Version) { // This could be a case of amnesia (backup / restore). throw Fx.Exception.AsError(new InvalidOperationException(SRCore.InstanceStoreBoundSameVersionTwice)); } throw Fx.AssertAndThrow("All cases covered above."); } else { BoundHandles.Add(reference.InstanceHandle.Id, reference.InstanceHandle); return(true); } } finally { CancelReference(ref reference, ref handlesPendingResolution); } } }