public void Unlink(IListElement <T> listElement) { lock (this.updateLatch) { this.UnlinkUnsafe(listElement); } }
public bool IsLinked(IListElement <T> listElement) { lock (this.updateLatch) { return(this.IsLinkedUnsafe(listElement)); } }
public CategoryView() { InitializeComponent(); _excludeCommand = new CheckBoxElement(excludeCategories); _addCategoryCommand = new ButtonElement(addCategory); _addCategoryCommand.Execute += () => { if (AddCategory(AvailableCategories.SelectedItem)) { AvailableCategories.SelectedItem = null; } }; _removeCategoryCommand = new ButtonElement(removeCategory); _removeCategoryCommand.Execute += () => { if (RemoveCategory(SelectedCategories.SelectedItem)) { SelectedCategories.SelectedItem = null; } }; _availableCategories = new ListElement(availableCatagories); _availableCategories.Sorted = true; _availableCategories.MouseItemDoubleClick += (sender, args) => AddCategory(args.Value); _selectedCategories = new ListElement(selectedCatagories); _selectedCategories.MouseItemDoubleClick += (sender, args) => RemoveCategory(args.Value); }
public OperationLockContext(ReliableConcurrentQueue <T> queue, IListElement <T> listElement, UnlockSource unlockSource, ITransaction tx, DateTime startTime) { this.queue = queue; this.ListElement = listElement; this.UnlockSource = unlockSource; this.Transaction = tx; this.OperationStartTime = startTime; }
public void AddListElement(IListElement <T> listElement) { if (this.HasListElement(listElement)) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.AddListElement", "!this.HasListElement(listElement)"); } this.ListElements[listElement.Id] = (ListElement)listElement; }
public void AddListElement(IListElement <T> listElement) { var positionBeforeListElements = (int)this.writer.BaseStream.Position; this.writer.Write(listElement.Id); this.valueSerializer.Write(listElement.Value, this.writer); this.listElementsBytes += (int)this.writer.BaseStream.Position - positionBeforeListElements; this.ListElementsCount++; }
public void RemoveListElement(IListElement <T> listElement) { this.AssertUnlinked(listElement); ListElement removed; var res = this.ListElements.TryRemove(listElement.Id, out removed); if (!res) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.RemoveListElement", "res"); } if (removed != (ListElement)listElement) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.RemoveListElement", "removed == (ReliableQueueListElement)listElement"); } }
/// <summary> /// Whenever an element is linked /// Set the result of the first waiting dequeuer. /// Should be called under the update latch /// </summary> /// <returns>True if there was a dequeuer waiting and we could set its result, False otherwise</returns> private bool TryNotifyDequeuer(IListElement <T> listElement) { TaskCompletionSource <ConditionalValue <IListElement <T> > > res; // While we have a waiting dequeuer while (this.dequeuerQueue.TryDequeue(out res)) { // If the dequeuers result can be set, then we are done, return true if (res.TrySetResult(new ConditionalValue <IListElement <T> >(true, listElement))) { return(true); } } // There was no waiting dequeuer return(false); }
public static async Task <IEnumerable <IListElement <T> > > ReadAsync(Stream stream, IStateSerializer <T> stateSerializer, string traceType) { var listElementsCountSegment = new ArraySegment <byte>(new byte[sizeof(int)]); var listElementsBytesSegment = new ArraySegment <byte>(new byte[sizeof(int)]); var listElementsCount = await SerializationHelper.ReadIntAsync(listElementsCountSegment, stream).ConfigureAwait(false); if (listElementsCount < 0) { throw new InvalidDataException(string.Format("Unexpected listElementsCount: {0}", listElementsCount)); } var listElementsBytes = await SerializationHelper.ReadIntAsync(listElementsBytesSegment, stream).ConfigureAwait(false); if (listElementsBytes < 0) { throw new InvalidDataException(string.Format("Unexpected listElementsBytes: {0}", listElementsBytes)); } using (var reader = new InMemoryBinaryReader(new MemoryStream())) { reader.BaseStream.SetLength(listElementsBytes + sizeof(ulong)); await SerializationHelper.ReadBytesAsync(new ArraySegment <byte>(reader.BaseStream.GetBuffer()), listElementsBytes + sizeof(ulong), stream) .ConfigureAwait(false); var listElements = new IListElement <T> [listElementsCount]; for (var i = 0; i < listElementsCount; i++) { var id = reader.ReadInt64(); var value = stateSerializer.Read(reader); // if this tries to read beyond the end of the stream, listElementsBytes was incorrect (too small) listElements[i] = DataStore <T> .CreateQueueListElement(id, value, traceType, ListElementState.EnqueueApplied); } var readCRC = reader.ReadUInt64(); var calcCRC = CRC64.ToCRC64(new[] { listElementsCountSegment, listElementsBytesSegment, new ArraySegment <byte>(reader.BaseStream.GetBuffer(), 0, listElementsBytes), }); if (readCRC != calcCRC) { throw new InvalidDataException(string.Format("CRC mismatch. Read: {0} Calculated: {1}", readCRC, calcCRC)); } return(listElements); } }
public void LinkTail(IListElement <T> listElement) { this.AssertUnlinked(listElement); lock (this.updateLatch) { switch (this.queueMode) { // IReliableConcurrentQueue case RCQMode.NonBlocking: { this.LinkTailUnsafe(listElement); break; } // IReliableConcurrentBlockingQueue case RCQMode.Blocking: { bool waitingDeq = false; if (this.dequeuersState == DequeuerState.OnPrimary) { waitingDeq = this.TryNotifyDequeuer(listElement); } else { this.AssertNoDequeuer(); } if (!waitingDeq) { // If there was no dequeuer waiting, link the element this.LinkTailUnsafe(listElement); } break; } default: TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.LinkTail", "Invalid QueueMode : {0}", this.queueMode); break; } } }
private bool IsTail(IListElement <T> listElement) { if (this.Tail != listElement) { return(false); } if (listElement.Next != null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.IsTail", "Tail must have null Next pointer"); } if ((this.Head == listElement) != (listElement.Previous == null)) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.IsTail", "If the listElement is also the head, it must not have a valid previous pointer. Otherwise, it must have a valid previous pointer."); } return(true); }
private bool IsHead(IListElement <T> listElement) { if (this.Head != listElement) { return(false); } if (listElement.Previous != null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.IsHead", "Head must have null Previous pointer"); } if ((listElement == this.Tail) != (listElement.Next == null)) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.IsHead", "If the listElement is also the tail, it must not have a valid next pointer. Otherwise, it must have a valid next pointer."); } return(true); }
public void AssertLinked(IListElement <T> listElement) { if (listElement == null) { TestableAssertHelper.FailArgumentNull(this.traceType, "DataStore.AssertLinked", "listElement"); } if (!this.IsLinked(listElement)) { TestableAssertHelper.FailInvalidOperation( this.traceType, "DataStore.AssertLinked", "listElement <id: {0}, next: {1}, previous: {2}, state: {3}> is not linked.", listElement.Id, listElement.Next != null ? listElement.Next.Id : ListElement.ForbiddenId, listElement.Previous != null ? listElement.Previous.Id : ListElement.ForbiddenId, listElement.State); } }
/// <summary> /// Should be called under the update latch /// <paramref name="listElement"/> must be unlinked, Caller must Assert on this /// </summary> /// <param name="listElement"></param> private void LinkTailUnsafe(IListElement <T> listElement) { var queueListElement = (ListElement)listElement; if (this.Tail == null) { if (this.Head != null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.LinkTailUnsafe", "this.Head == null"); } if (this.LinkedCount != 0) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.LinkTailUnsafe", "this.LinkedCount == 0"); } this.head = queueListElement; this.tail = queueListElement; } else { if (this.Head == null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.LinkTailUnsafe", "this.Head != null"); } if (this.LinkedCount == 0) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.LinkTailUnsafe", "this.LinkedCount != 0"); } this.tail.Next = queueListElement; queueListElement.Previous = this.tail; this.tail = queueListElement; } this.LinkedCount++; }
/// <summary> /// Unlink a listElement from the list. Must be called under the update lock. /// </summary> /// <param name="listElement"></param> private void UnlinkUnsafe(IListElement <T> listElement) { if (listElement == null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.UnlinkUnsafe", "listElement != null"); } if (this.LinkedCount == 0) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.UnlinkUnsafe", "this.LinkedCount != 0"); } if (this.Head == null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.UnlinkUnsafe", "this.Head != null"); } if (this.Head.Previous != null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.UnlinkUnsafe", "this.Head.Previous == null"); } if (this.Tail == null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.UnlinkUnsafe", "this.Tail != null"); } if (this.Tail.Next != null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.UnlinkUnsafe", "this.Tail.Next == null"); } if (this.LinkedCount != 1 && listElement.Next == null && listElement.Previous == null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.UnlinkUnsafe", "!(this.LinkedCount != 1 && listElement.Next == null && listElement.Previous == null)"); } var queueListElement = (ListElement)listElement; if (listElement.Previous == null) { if (listElement != this.Head) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.UnlinkUnsafe", "listElement == this.Head"); } this.head = this.head.Next; } else { queueListElement.Previous.Next = queueListElement.Next; } if (listElement.Next == null) { if (listElement != this.Tail) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.UnlinkUnsafe", "listElement == this.Tail"); } this.tail = queueListElement.Previous; } else { queueListElement.Next.Previous = queueListElement.Previous; } queueListElement.Previous = null; queueListElement.Next = null; this.LinkedCount--; }
public bool HasListElement(IListElement <T> listElement) { return(this.HasListElement(listElement.Id)); }
private bool IsLinkedUnsafe(IListElement <T> listElement) { // The order of the following checks is significant // is this listElement in the dictionary at all if (!this.HasListElement(listElement)) { if (listElement.Next != null) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.IsLinkedUnsafe", "sanity: If this listElement is not in the dictionary, it must not have a valid next pointer."); } if (listElement.Previous != null) { TestableAssertHelper.FailInvalidOperation( this.traceType, "DataStore.IsLinkedUnsafe", "sanity: If this listElement is not in the dictionary, it must not have a valid previous pointer."); } return(false); } // is it linked at the head or the tail if (this.IsHead(listElement) || this.IsTail(listElement)) { return(true); } // is it not linked at all if (listElement.Next == null && listElement.Previous == null) { return(false); } // is it linked in the middle if (listElement.Next != null && listElement.Previous != null) { if (!(this.HasListElement(listElement.Next))) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.IsLinkedUnsafe", "sanity: listElement.Next must be in the dictionary."); } if (listElement.Next.Previous != listElement) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.IsLinkedUnsafe", "sanity: listElement.Next.Previous must be listElement."); } if (!(this.HasListElement(listElement.Previous))) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.IsLinkedUnsafe", "sanity: listElement.Previous must be in the dictionary."); } if (listElement.Previous.Next != listElement) { TestableAssertHelper.FailInvalidOperation(this.traceType, "DataStore.IsLinkedUnsafe", "sanity: listElement.Previous.Next must be listElement."); } return(true); } // it is partially linked and thus incorrect TestableAssertHelper.FailInvalidOperation( this.traceType, "DataStore.IsLinkedUnsafe", "Invalid listElement state: <id: {0}, next: {1}, previous: {2}, state: {3}>", listElement.Id, listElement.Next != null ? listElement.Next.Id : ListElement.ForbiddenId, listElement.Previous != null ? listElement.Previous.Id : ListElement.ForbiddenId, listElement.State); throw new InvalidOperationException("Invalid listElement state: " + listElement); // unreachable }
public static IListElement Setup(this IListElement element, Action <View> setup) { return(new SetupListElement(element, setup)); }
/// <summary> /// Initializes a new instance of the <see cref="ListElementExpression"/> class. /// </summary> /// <param name="element">The element.</param> public ListElementExpression([NotNull] IListElement element) : base(element) { _element = element; }