Пример #1
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));
                });
            });
        }
Пример #2
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));
                            }
                    });
                }));
            }
Пример #3
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++;
            });
        }
Пример #4
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);
                        }
                }));
            }