public void Free() { if (!this.providerObjectSet) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.HandleFreedBeforeInitialized)); } if (!IsValid) { return; } List <InstanceHandleReference> handlesPendingResolution = null; WaitForEventsAsyncResult resultToCancel = null; try { bool needNotification = false; InstancePersistenceContext currentContext = null; lock (ThisLock) { if (!IsValid) { return; } IsValid = false; IEnumerable <XName> eventsToUnbind = null; if (this.pendingOwnerEvents != null && this.pendingOwnerEvents.Count > 0) { eventsToUnbind = this.pendingOwnerEvents.Select(persistenceEvent => persistenceEvent.Name); } if (this.boundOwnerEvents != null && this.boundOwnerEvents.Count > 0) { eventsToUnbind = eventsToUnbind == null ? this.boundOwnerEvents : eventsToUnbind.Concat(this.boundOwnerEvents); } if (eventsToUnbind != null) { Fx.Assert(Owner != null, "How do we have owner events without an owner."); Store.RemoveHandleFromEvents(this, eventsToUnbind, Owner); } if (this.waitResult != null) { resultToCancel = this.waitResult; this.waitResult = null; } if (OperationPending) { if (AcquirePending != null) { // If in this stage, we need to short-circuit the pending transaction. Fx.Assert(CurrentTransactionalAsyncResult != null, "Should have a pending transaction if we are waiting for it."); CurrentTransactionalAsyncResult.WaitForHostTransaction.Set(); this.needFreedNotification = true; } else { // Here, just notify the currently executing command. Fx.Assert(CurrentExecutionContext != null, "Must have either this or AcquirePending set."); currentContext = CurrentExecutionContext; } } else { needNotification = true; if (this.inProgressBind != null) { Owner.CancelBind(ref this.inProgressBind, ref handlesPendingResolution); } else if (Version != -1) { // This means the handle was successfully bound in the past. Need to remove it from the table of handles. Owner.Unbind(this); } } } if (currentContext != null) { // Need to do this not in a lock. currentContext.NotifyHandleFree(); lock (ThisLock) { if (OperationPending) { this.needFreedNotification = true; // Cancel any pending lock reclaim here. if (this.inProgressBind != null) { Fx.Assert(Owner != null, "Must be bound to owner to have an inProgressBind for the lock in CancelReclaim."); // Null reason defaults to OperationCanceledException. (Defer creating it since this might not be a // reclaim attempt, but we don't know until we take the HandlesLock.) Owner.FaultBind(ref this.inProgressBind, ref handlesPendingResolution, null); } } else { needNotification = true; } } } if (needNotification) { Store.FreeInstanceHandle(this, ProviderObject); } } finally { if (resultToCancel != null) { resultToCancel.Canceled(); } InstanceOwner.ResolveHandles(handlesPendingResolution); } }
public void Free() { if (!this.providerObjectSet) { throw Fx.Exception.AsError(new InvalidOperationException(SRCore.HandleFreedBeforeInitialized)); } if (this.IsValid) { List <InstanceHandleReference> handlesPendingResolution = null; WaitForEventsAsyncResult waitResult = null; try { bool flag = false; InstancePersistenceContext currentExecutionContext = null; lock (this.ThisLock) { if (!this.IsValid) { return; } this.IsValid = false; IEnumerable <XName> first = null; if ((this.pendingOwnerEvents != null) && (this.pendingOwnerEvents.Count > 0)) { first = from persistenceEvent in this.pendingOwnerEvents select persistenceEvent.Name; } if ((this.boundOwnerEvents != null) && (this.boundOwnerEvents.Count > 0)) { first = (first == null) ? this.boundOwnerEvents : first.Concat <XName>(this.boundOwnerEvents); } if (first != null) { this.Store.RemoveHandleFromEvents(this, first, this.Owner); } if (this.waitResult != null) { waitResult = this.waitResult; this.waitResult = null; } if (this.OperationPending) { if (this.AcquirePending != null) { this.CurrentTransactionalAsyncResult.WaitForHostTransaction.Set(); this.needFreedNotification = true; } else { currentExecutionContext = this.CurrentExecutionContext; } } else { flag = true; if (this.inProgressBind != null) { this.Owner.CancelBind(ref this.inProgressBind, ref handlesPendingResolution); } else if (this.Version != -1L) { this.Owner.Unbind(this); } } } if (currentExecutionContext != null) { currentExecutionContext.NotifyHandleFree(); lock (this.ThisLock) { if (this.OperationPending) { this.needFreedNotification = true; if (this.inProgressBind != null) { this.Owner.FaultBind(ref this.inProgressBind, ref handlesPendingResolution, null); } } else { flag = true; } } } if (flag) { this.Store.FreeInstanceHandle(this, this.ProviderObject); } } finally { if (waitResult != null) { waitResult.Canceled(); } InstanceOwner.ResolveHandles(handlesPendingResolution); } } }