Пример #1
0
        private void AcquireTakeCancellationHandler(object _acquireNode, bool canceling)
        {
            LinkedListNode <AsyncTake> acquireNode = (LinkedListNode <AsyncTake>)_acquireNode;
            AsyncTake acquire = acquireNode.Value;

            if (acquire.TryLock())
            {
                // To access shared mutable state we must acquire the lock
                lock (theLock)
                {
                    asyncTakes.Remove(acquireNode);
                }

                // Release the resources associated with the async acquire.
                acquire.Dispose(canceling);

                // Complete the TaskCompletionSource to RanToCompletion (timeout)
                // or Canceled final state.
                if (canceling)
                {
                    acquire.SetCanceled();
                }
                else
                {
                    acquire.SetResult(default);
Пример #2
0
    /**
     * Cancellation handlers
     */

    /**
     * Try to cancel an async take request.
     */
    private void TakeCancellationHandler(object _takeNode, bool canceling)
    {
        LinkedListNode <AsyncTake> takeNode = (LinkedListNode <AsyncTake>)_takeNode;
        AsyncTake take = null;

        // Acquire the lock to access the shared mutable state
        lock (theLock) {
            /**
             * Here, the async take request can be completed or canceled
             */
            if (!takeNode.Value.done)
            {
                // Remove the async take from the queue and mark it as canceled
                asyncTakes.Remove(takeNode);
                take      = takeNode.Value;
                take.done = true;
            }
        }
        if (take != null)
        {
            // Dispose resources associated with this async take request.
            take.Dispose(canceling);

            // Complete the underlying task properly.
            if (canceling)
            {
                take.SetCanceled();
            }
            else
            {
                take.SetResult(null);
            }
        }
    }
Пример #3
0
        private void TakeCancellationHandler(object request, bool canceling)
        {
            LinkedListNode <AsyncTake> node = (LinkedListNode <AsyncTake>)request;
            AsyncTake take = node.Value;

            if (take.TryLock())
            {
                lock (_lock) {
                    if (node.List != null)
                    {
                        _asyncTakes.Remove(node);
                    }
                }

                take.Dispose();

                if (canceling)
                {
                    take.SetCanceled();
                }
                else
                {
                    take.SetResult(default);
Пример #4
0
    /**
     *	Synchronous interface based on asynchronous TAP interface
     */

    /**
     * Try to cancel an asynchronous take represented by its task.
     */
    private bool CancelTakeByTask(Task <T> takeTask)
    {
        AsyncTake take = null;

        lock (theLock) {
            foreach (AsyncTake _take in asyncTakes)
            {
                if (_take.Task == takeTask)
                {
                    take = _take;
                    asyncTakes.Remove(_take);
                    take.done = true;
                    break;
                }
            }
        }
        if (take != null)
        {
            take.Dispose();
            take.SetCanceled();
        }
        return(take != null);
    }
Пример #5
0
    /**
     * Put a message on the queue asynchronously enabling, optionally,
     * a timeout and/or cancellation.
     */
    public Task <bool> PutAsync(T sentMessage, int timeout = Timeout.Infinite,
                                CancellationToken cToken   = default(CancellationToken))
    {
        Task <bool> putTask = null;
        AsyncTake   take    = null;

        lock (theLock) {
            if (state != OPERATING)
            {
                throw new InvalidOperationException();
            }
            if ((putIdx - takeIdx) < capacity)
            {
                // Do an immediate put
                messageRoom[putIdx++ & mask] = sentMessage;
                putTask = trueTask;

                // Try to satisfy a pending async take request.
                if (asyncTakes.Count > 0)
                {
                    take = asyncTakes.First.Value;
                    asyncTakes.RemoveFirst();
                    take.receivedMessage = messageRoom[takeIdx++ & mask];
                    take.done            = true;
                }
            }
            else
            {
                // The current thread must block, so we check for immediate cancelers
                if (timeout == 0)
                {
                    return(falseTask);
                }

                // If a cancellation was requested return a task in the Canceled state
                if (cToken.IsCancellationRequested)
                {
                    return(Task.FromCanceled <bool>(cToken));
                }

                // Create a waiter node and insert it in the wait queue
                AsyncPut put = new AsyncPut(sentMessage, cToken);
                LinkedListNode <AsyncPut> putNode = asyncPuts.AddLast(put);

                /**
                 * Activate the specified cancelers owning the lock.
                 * Since the timeout handler acquires the lock before use the "put.timer" and
                 * "put.cTokenRegistration" the assignements will be visible.
                 */
                if (timeout != Timeout.Infinite)
                {
                    put.timer = new Timer(putTimeoutHandler, putNode, timeout, Timeout.Infinite);
                }

                /**
                 * If the cancellation token is already in the canceled state, the cancellation
                 * will run immediately and synchronously, which causes no damage because the
                 * implicit locks can be acquired recursively and this is a terminal processing.
                 */
                if (cToken.CanBeCanceled)
                {
                    put.cTokenRegistration = cToken.Register(putCancellationHandler, putNode);
                }

                // Set the result task that represents the asynchronous operation
                putTask = put.Task;
            }
        }
        // If we released any putter, cancel its cancellers and complete its tasks.
        if (take != null)
        {
            take.Dispose();
            take.SetResult(take.receivedMessage);
        }
        return(putTask);
    }
Пример #6
0
    /**
     * Asynchronous TAP interface
     */

    /**
     * Take a message from the queue asynchronously enabling, optionally,
     * timeout and/or cancellation.
     */
    public Task <T> TakeAsync(int timeout = Timeout.Infinite,
                              CancellationToken cToken = default(CancellationToken))
    {
        Task <T> takeTask = null;
        AsyncPut put      = null;

        lock (theLock) {
            if (putIdx - takeIdx > 0)
            {
                // Immediate take
                takeTask = Task.FromResult <T>(messageRoom[takeIdx++ & mask]);

                // Try to satisfy a pending async put request
                if (asyncPuts.Count > 0)
                {
                    put = asyncPuts.First.Value;
                    asyncPuts.RemoveFirst();
                    messageRoom[putIdx++ & mask] = put.sentMessage;
                    put.done = true;
                }

                /**
                 * If the queue is in the COMPLETING state, the message queue is empty and
                 * we released the last pending put, then transition the queue to the
                 * COMPLETED state.
                 */
                if (putIdx == takeIdx && state == COMPLETING && asyncPuts.Count == 0)
                {
                    state = COMPLETED;
                }
            }
            else
            {
                // If the queue was already completed or an immediate take was spedified
                // return failure.
                if (state != OPERATING)
                {
                    throw new InvalidOperationException();
                }
                if (timeout == 0)
                {
                    return(nullTask);
                }

                // If a cancellation was requested return a task in the Canceled state
                if (cToken.IsCancellationRequested)
                {
                    return(Task.FromCanceled <T>(cToken));
                }

                // Create a waiter node and insert it in the wait queue
                AsyncTake take = new AsyncTake(cToken);
                LinkedListNode <AsyncTake> takeNode = asyncTakes.AddLast(take);

                /**
                 * Activate the specified cancellers owning the lock.
                 * Since the timeout handler acquires the lock before use the "take.timer" and
                 * "take.cTokenRegistration" the assignements will be visible.
                 */
                if (timeout != Timeout.Infinite)
                {
                    take.timer = new Timer(takeTimeoutHandler, takeNode, timeout, Timeout.Infinite);
                }

                /**
                 * If the cancellation token is already in the cancelled state, the cancellation
                 * will run immediately and synchronously, which causes no damage because the
                 * implicit locks can be acquired recursively and this is a terminal processing.
                 */
                if (cToken.CanBeCanceled)
                {
                    take.cTokenRegistration = cToken.Register(takeCancellationHandler, takeNode);
                }

                // Set the result task that represents the asynchronous operation
                takeTask = take.Task;
            }
        }
        // If we released any putter, cancel its cancellers and complete its task.
        if (put != null)
        {
            put.Dispose();
            put.SetResult(true);
        }
        return(takeTask);
    }