protected void ResetEvent(InstancePersistenceEvent persistenceEvent, InstanceOwner owner) { if (persistenceEvent == null) { throw Fx.Exception.ArgumentNull(nameof(persistenceEvent)); } if (owner == null) { throw Fx.Exception.ArgumentNull(nameof(owner)); } lock (ThisLock) { if (!_owners.TryGetValue(owner.InstanceOwnerId, out WeakReference ownerReference) || !object.ReferenceEquals(ownerReference.Target, owner)) { throw Fx.Exception.Argument(nameof(owner), SR.OwnerBelongsToWrongStore); } if (!owner.Events.TryGetValue(persistenceEvent.Name, out InstanceNormalEvent normal)) { return; } if (normal.IsSignaled) { normal.IsSignaled = false; if (normal.BoundHandles.Count == 0 && normal.PendingHandles.Count == 0) { owner.Events.Remove(persistenceEvent.Name); } } } }
internal void Signaled(InstancePersistenceEvent persistenceEvent) { Signaled(new List <InstancePersistenceEvent>(1) { persistenceEvent }); }
// Must be called under ThisLock. Doesn't validate the InstanceOwner. private InstanceNormalEvent GetOwnerEventHelper(InstancePersistenceEvent persistenceEvent, InstanceOwner owner) { if (!owner.Events.TryGetValue(persistenceEvent.Name, out InstanceNormalEvent normal)) { normal = new InstanceNormalEvent(persistenceEvent); owner.Events.Add(persistenceEvent.Name, normal); } return(normal); }
internal void PendHandleToEvent(InstanceHandle handle, InstancePersistenceEvent persistenceEvent, InstanceOwner owner) { lock (ThisLock) { Fx.Assert(_owners.ContainsKey(owner.InstanceOwnerId), "InstanceHandle called PendHandleToEvent on wrong InstanceStore!!"); Fx.Assert(object.ReferenceEquals(_owners[owner.InstanceOwnerId].Target, owner), "How did multiple of the same owner become simultaneously active?"); InstanceNormalEvent normal = GetOwnerEventHelper(persistenceEvent, owner); Fx.Assert(!normal.PendingHandles.Contains(handle), "Should not have already pended the handle."); Fx.Assert(!normal.BoundHandles.Contains(handle), "Should not be able to pend an already-bound handle."); normal.PendingHandles.Add(handle); } }
internal InstancePersistenceEvent AddHandleToEvent(InstanceHandle handle, InstancePersistenceEvent persistenceEvent, InstanceOwner owner) { lock (ThisLock) { Fx.Assert(_owners.ContainsKey(owner.InstanceOwnerId), "InstanceHandle called AddHandleToEvent on wrong InstanceStore!!"); Fx.Assert(object.ReferenceEquals(_owners[owner.InstanceOwnerId].Target, owner), "How did multiple instances of the same owner become simultaneously active?"); InstanceNormalEvent normal = GetOwnerEventHelper(persistenceEvent, owner); Fx.Assert(normal.PendingHandles.Contains(handle), "Should have already pended the handle."); Fx.Assert(!normal.BoundHandles.Contains(handle), "Should not be able to add a handle to an event twice."); normal.BoundHandles.Add(handle); normal.PendingHandles.Remove(handle); return(normal.IsSignaled ? normal : null); } }
internal void EventReady(InstancePersistenceEvent persistenceEvent) { WaitForEventsAsyncResult resultToComplete = null; lock (ThisLock) { if (_waitResult != null) { resultToComplete = _waitResult; _waitResult = null; } } if (resultToComplete != null) { resultToComplete.Signaled(persistenceEvent); } }
protected void SignalEvent(InstancePersistenceEvent persistenceEvent, InstanceOwner owner) { if (persistenceEvent == null) { throw Fx.Exception.ArgumentNull(nameof(persistenceEvent)); } if (owner == null) { throw Fx.Exception.ArgumentNull(nameof(owner)); } InstanceNormalEvent normal; InstanceHandle[] handlesToNotify = null; lock (ThisLock) { if (!_owners.TryGetValue(owner.InstanceOwnerId, out WeakReference ownerReference) || !object.ReferenceEquals(ownerReference.Target, owner)) { throw Fx.Exception.Argument(nameof(owner), SR.OwnerBelongsToWrongStore); } normal = GetOwnerEventHelper(persistenceEvent, owner); if (!normal.IsSignaled) { normal.IsSignaled = true; if (normal.BoundHandles.Count > 0) { handlesToNotify = normal.BoundHandles.ToArray(); } } } if (handlesToNotify != null) { foreach (InstanceHandle handle in handlesToNotify) { handle.EventReady(normal); } } }
internal void BindOwnerEvent(InstancePersistenceEvent persistenceEvent) { lock (ThisLock) { Fx.Assert(OperationPending, "Should only be called during an operation."); Fx.Assert(AcquirePending == null, "Should only be called after acquiring the transaction."); Fx.Assert(Owner != null, "Must be bound to owner to have an owner-scoped event."); if (IsValid && (_boundOwnerEvents == null || !_boundOwnerEvents.Contains(persistenceEvent.Name))) { if (_pendingOwnerEvents == null) { _pendingOwnerEvents = new HashSet <InstancePersistenceEvent>(); } else if (_pendingOwnerEvents.Contains(persistenceEvent)) { return; } _pendingOwnerEvents.Add(persistenceEvent); Store.PendHandleToEvent(this, persistenceEvent, Owner); } } }
internal InstanceNormalEvent(InstancePersistenceEvent persistenceEvent) : base(persistenceEvent.Name) { }
// Returns null if an InstanceHandleConflictException should be thrown. internal InstanceView Commit(InstanceView newState) { Fx.Assert(newState != null, "Null view passed to Commit."); newState.MakeReadOnly(); View = newState; List <InstanceHandleReference> handlesPendingResolution = null; InstanceHandle handleToFree = null; List <InstancePersistenceEvent> normals = null; WaitForEventsAsyncResult resultToComplete = null; try { lock (ThisLock) { if (_inProgressBind != null) { // If there's a Version, it should be committed. if (Version != -1) { if (!Owner.TryCompleteBind(ref _inProgressBind, ref handlesPendingResolution, out handleToFree)) { return(null); } } else { Fx.Assert(OperationPending, "Should have cancelled this bind in FinishOperation."); Fx.Assert(AcquirePending == null, "Should not be in Commit during AcquirePending."); Owner.CancelBind(ref _inProgressBind, ref handlesPendingResolution); } } if (_pendingOwnerEvents != null && IsValid) { if (_boundOwnerEvents == null) { _boundOwnerEvents = new HashSet <XName>(); } foreach (InstancePersistenceEvent persistenceEvent in _pendingOwnerEvents) { if (!_boundOwnerEvents.Add(persistenceEvent.Name)) { Fx.Assert("Should not have conflicts between pending and bound events."); continue; } InstancePersistenceEvent normal = Store.AddHandleToEvent(this, persistenceEvent, Owner); if (normal != null) { if (normals == null) { normals = new List <InstancePersistenceEvent>(_pendingOwnerEvents.Count); } normals.Add(normal); } } _pendingOwnerEvents = null; if (normals != null && _waitResult != null) { resultToComplete = _waitResult; _waitResult = null; } } return(View); } } finally { InstanceOwner.ResolveHandles(handlesPendingResolution); // This is a convenience, it is not required for correctness. if (handleToFree != null) { Fx.Assert(!object.ReferenceEquals(handleToFree, this), "Shouldn't have been told to free ourselves."); handleToFree.Free(); } if (resultToComplete != null) { resultToComplete.Signaled(normals); } } }