Example #1
0
        public void Free()
        {
            if (!_providerObjectSet)
            {
                throw Fx.Exception.AsError(new InvalidOperationException(SR.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 (_pendingOwnerEvents != null && _pendingOwnerEvents.Count > 0)
                    {
                        eventsToUnbind = _pendingOwnerEvents.Select(persistenceEvent => persistenceEvent.Name);
                    }
                    if (_boundOwnerEvents != null && _boundOwnerEvents.Count > 0)
                    {
                        eventsToUnbind = eventsToUnbind == null ? _boundOwnerEvents : eventsToUnbind.Concat(_boundOwnerEvents);
                    }
                    if (eventsToUnbind != null)
                    {
                        Fx.Assert(Owner != null, "How do we have owner events without an owner.");
                        Store.RemoveHandleFromEvents(this, eventsToUnbind, Owner);
                    }
                    if (_waitResult != null)
                    {
                        resultToCancel = _waitResult;
                        _waitResult    = null;
                    }

                    if (OperationPending)
                    {
                        if (AcquirePending != null)
                        {
                            _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 (_inProgressBind != null)
                        {
                            Owner.CancelBind(ref _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)
                        {
                            _needFreedNotification = true;

                            // Cancel any pending lock reclaim here.
                            if (_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 _inProgressBind, ref handlesPendingResolution, null);
                            }
                        }
                        else
                        {
                            needNotification = true;
                        }
                    }
                }

                if (needNotification)
                {
                    Store.FreeInstanceHandle(this, ProviderObject);
                }
            }
            finally
            {
                if (resultToCancel != null)
                {
                    resultToCancel.Canceled();
                }

                InstanceOwner.ResolveHandles(handlesPendingResolution);
            }
        }