private async Task <node> getNodeAt( long index, IAccessContext <CSScope> context) { return(await context.InChild( new CSScope(valueScope : InfiniteIntervalScope.Create( RWScope.Read, 0, index + 1), name : $"scope for getNodeAt {index}"), async subContext => { await subContext.UntilAvailable(new CSScope(valueScope : InfiniteIntervalScope.Create(RWScope.Read, 0, 1), name : $"UntilAvailable scope in getNodeAt {index}")); node currentNode = state.FirstNode; for (long i = 1; i <= index; i++) { await subContext.UntilAvailable(new CSScope( valueScope: InfiniteIntervalScope.Create( RWScope.Read, i, i + 1), name: "UntilAvailable scope in " + $"getNodeAt {index}")); currentNode = currentNode.Successor; } return currentNode; })); }
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)); }); }); }
private async Task <Tuple <node, int> > getLastNode( node startNode, int startIndex, IAccessContext <CSScope> context) { return(await context.InChild( new CSScope(valueScope : InfiniteIntervalScope.Create( RWScope.Read, startIndex + 1, null)), async subContext => { node currentNode = startNode; for (int index = startIndex + 1; ; index++) { /* read the node at position index */ await subContext.UntilAvailable(new CSScope(valueScope: InfiniteIntervalScope.Create( RWScope.Read, index, index + 1))); if (currentNode.Successor == null) { return Tuple.Create(currentNode, index - 1); } currentNode = currentNode.Successor; subContext.RequiredScope = new CSScope(valueScope: InfiniteIntervalScope.Create( RWScope.Read, index + 1, null)); } })); }
private async Task <Tuple <node, int> > getLastNode( IAccessContext <CSScope> context, node startNode = null, int startIndex = -1) { if (startNode == null) { startIndex = -1; } return(await context.InChild(new CSScope( valueScope : InfiniteIntervalScope.Create( RWScope.Read, startIndex + 1, null), name : "scope for getLastNode"), async subContext => { if (startNode == null) { node firstNode = await getFirstNode(subContext); if (firstNode == null) { return null; } startNode = firstNode; startIndex = 0; } var t = getLastNode(startNode, startIndex, subContext); subContext.Dispose(); return await t; })); }
/// <remarks> /// No child context of <paramref name="context"/> /// may be created und employed before /// the invocation of this method because /// this method itself does not create an own child context. /// </remarks> private async Task <node> getFirstNode(IAccessContext <CSScope> context) { await context.UntilAvailable(new CSScope( valueScope : InfiniteIntervalScope.Create( RWScope.Read, 0, 1))); return(state.FirstNode); }
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)); } }); })); }
public CSScope( RWScope countScope = RWScope.None, IInfiniteIntervalScope <RWScope> valueScope = null, string name = null) { if (valueScope == null) { valueScope = InfiniteIntervalScope.Create(RWScope.None); } CountScope = countScope; ValueScope = valueScope; Name = name; }
private static async Task addFibonacciNumbers( ContextualStream <BigInteger> stream, int count = 30) { await TaskCollector.With(async tc => { await stream.InChild(new CSScope( RWScope.ReadWrite, InfiniteIntervalScope.Create( RWScope.ReadWrite, 0, null)), async childStream => { await Task.Yield(); IAppender <BigInteger> appender = childStream.GetAppender(); BigInteger a = 1, b = 1; tc.Add(appender.Append(a)); /* FIXME: Users of appender generally don’t know * the internals of ContextualStream. * Poss. solution: IAppender.MaxRequiredScope. * Then it would also be useful, if (the) access scopes * could be merged. */ childStream.Context.RequiredScope = new CSScope( RWScope.ReadWrite, InfiniteIntervalScope.Create( RWScope.ReadWrite, 1, null)); tc.Add(appender.Append(b)); childStream.Context.RequiredScope = new CSScope( RWScope.ReadWrite, InfiniteIntervalScope.Create( RWScope.ReadWrite, 2, null)); for (int i = 2; i < count; i++) { BigInteger c = a + b; await Task.Delay(250); a = b; b = c; tc.Add(appender.Append(c)); childStream.Context.RequiredScope = new CSScope( RWScope.ReadWrite, InfiniteIntervalScope.Create( RWScope.ReadWrite, i + 1, null)); } }); }); }
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 async Task Append(T value) { await TaskCollector.With(async tc => { using (var lknChild = lastKnownNode.CreateChild(RWScope.ReadWrite)) using (var lknIndexChild = lastKnownNodeIndex.CreateChild(RWScope.ReadWrite)) using (var streamChildContext = stream.Context.CreateChildWithin( new CSScope( RWScope.ReadWrite, InfiniteIntervalScope.Create( RWScope.ReadWrite, 0, null)))) { node lkn = await tc.Adding(lknChild.Get()); int lknIndex; if (lkn == null) { lknIndex = -1; } else { lknIndex = await tc.Adding(lknIndexChild.Get()); } Tuple <node, int> lastNodeInfo = await stream.getLastNode( streamChildContext, lkn, lknIndex); node newNode = new node { Value = value, Successor = null, }; tc.Add(stream.appendToLastNode( newNode, lastNodeInfo, streamChildContext)); streamChildContext.Dispose(); tc.Add(lknChild.Set(newNode.ToFuture())); tc.Add(lknIndexChild.Set( ((lastNodeInfo?.Item2 ?? -1) + 1).ToFuture())); } }); }
public static async Task PrintValues <T>(IChildContextualCreator < CSScope, ContextualStream <T> > subContextFactory) { await subContextFactory.InChild(new CSScope(valueScope: InfiniteIntervalScope.Create(RWScope.Read, 0, null)), async ints => { await TaskCollector.With(async tc => { IAsyncEnumerator <T> enumerator = ints.GetAsyncEnumerator(); while (await tc.Adding(enumerator.MoveNextAsync())) { T value = await tc.Adding(enumerator.GetCurrentAsync()); Console.WriteLine(value); } }); }); }
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); } })); }