private async Task add(T value, IAccessContext <CSScope> context) { await TaskCollector.With(async tc => { CSScope pessimisticScope = new CSScope(RWScope.ReadWrite, InfiniteIntervalScope.Create( RWScope.ReadWrite, 0, null), $"pessimistic scope for add-{value}"); await context.InChildWithin(pessimisticScope, async childContext => { Tuple <node, int> lastNodeInfo = await getLastNode(childContext); /* At this point, we don’t require write access * to the nodes from 0 to count - 1 anymore, * but IInfiniteIntervalScope is not granular enough * to represent that. * Read tasks for lower indexes could proceed. */ node newNode = new node { Successor = null, Value = value }; tc.Add(appendToLastNode( newNode, lastNodeInfo, childContext)); }); }); }
public IReactive <bool> MoveNextAsync() { return(Reactive.From <bool>(async resultResolver => { await TaskCollector.With(async tc => { using (ContextualStream <T> childStream = stream.CreateChildWithin(new CSScope(valueScope: InfiniteIntervalScope.Create( RWScope.Read, 0, null)))) using (IAccessContext <enumeratorScope> childEnumContext = context.CreateChild(new enumeratorScope( RWScope.ReadWrite, RWScope.ReadWrite))) { long curNextIndex = await readNextIndex(childEnumContext); CSScope readNextNodeScope = new CSScope(valueScope: InfiniteIntervalScope.Create(RWScope.Read, curNextIndex, curNextIndex + 1)); childStream.Context.RequiredScope = readNextNodeScope; node nextNode; if (curNextIndex == 0) { /* Erste Iteration. */ tc.Add(incrementNextIndex(childEnumContext)); nextNode = await childStream.getFirstNode( childStream.Context); } else { node curCurrentNode = await readCurrentNode(childEnumContext); if (curCurrentNode == null) { throw new InvalidOperationException( "The stream has already " + "been iterated through."); } tc.Add(incrementNextIndex(childEnumContext)); await childStream.Context.UntilAvailable(); nextNode = curCurrentNode.Successor; } resultResolver.Resolve(nextNode != null); childStream.Dispose(); tc.Add(setCurrentNode(nextNode, childEnumContext)); } }); })); }
private async Task appendToLastNode( node newNode, Tuple <node, int> lastNodeInfo, IAccessContext <CSScope> context) { await context.InChildWithin(async childContext => { if (lastNodeInfo == null) { /* Setting first node */ /* Requires an IInfiniteIntervalScope from 0 to infinity, * because setting the first node determines * could also change all other nodes. */ var scope = new CSScope( RWScope.ReadWrite, InfiniteIntervalScope.Create( RWScope.ReadWrite, 0, 1), $"scope for appendToLastNode {newNode.Value}"); /* TRAP: Using context instead of childContext here * may easily lead to a deadlock. */ childContext.RequiredScope = scope; /* Wait for all required scope before writing. */ await childContext.UntilAvailable(); state.FirstNode = newNode; } else { /* Set the new node */ int newIndex = lastNodeInfo.Item2 + 1; var scope = new CSScope( RWScope.ReadWrite, InfiniteIntervalScope.Create( RWScope.ReadWrite, newIndex, newIndex + 1)); childContext.RequiredScope = scope; await childContext.UntilAvailable(); lastNodeInfo.Item1.Successor = newNode; } state.Count++; }); }
public IReactive <T> GetCurrentAsync() { return(Reactive.From <T>(async resultResolver => { using (ContextualStream <T> childStream = stream.CreateChildWithin(new CSScope(valueScope: InfiniteIntervalScope.Create( RWScope.Read, 0, null)))) using (IAccessContext <enumeratorScope> childEnumContext = context.CreateChildWithin(new enumeratorScope( RWScope.Read, RWScope.Read))) { long curNextIndex = await readNextIndex(childEnumContext); childEnumContext.RequiredScope = new enumeratorScope(RWScope.Read); CSScope readValueScope = new CSScope(valueScope: InfiniteIntervalScope.Create( RWScope.Read, curNextIndex - 1, curNextIndex)); childStream.Context.RequiredScope = readValueScope; node curNode = await readCurrentNode(childEnumContext); childEnumContext.Dispose(); if (curNode == null) { throw new InvalidOperationException( "The enumerator is already disposed."); } await childStream.Context.UntilAvailable( readValueScope); resultResolver.Resolve(curNode.Value); } })); }