예제 #1
0
        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;
            }));
        }
예제 #2
0
        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));
                });
            });
        }
예제 #3
0
        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));
                }
            }));
        }
예제 #4
0
 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;
     }));
 }
예제 #5
0
        /// <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);
        }
예제 #6
0
            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));
                            }
                    });
                }));
            }
예제 #7
0
 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));
                    }
                });
            });
        }
예제 #9
0
        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++;
            });
        }
예제 #10
0
 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);
             }
         });
     });
 }
예제 #12
0
            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);
                        }
                }));
            }