Ejemplo n.º 1
0
        protected AsyncOperation?DequeueFirstAndGetNext(AsyncOperation first)
        {
            AsyncOperation?queue = Interlocked.CompareExchange(ref _queue, null, first);

            Debug.Assert(queue != null);
            if (object.ReferenceEquals(queue, first) || IsDisposed(queue))
            {
                return(null);
            }

            Debug.Assert(IsGate(queue));
            lock (queue)
            {
                if (queue.Next == first)               // we're the last -> single element
                {
                    Debug.Assert(first.Next == first); // verify we're a single element list
                    queue.Next = null;
                    return(null);
                }
                else
                {
                    AsyncOperation?last = queue.Next;
                    Debug.Assert(last != null);       // there is an element
                    Debug.Assert(last.Next == first); // we're first
                    last.Next  = first.Next;          // skip operation
                    first.Next = first;               // point to self
                    return(last.Next);
                }
            }
        }
            void IAsyncExecutionResultHandler.HandleAsyncResult(AsyncOperationResult aResult)
            {
                AsyncOperation?op = _executingOperation !;

                AsyncExecutionResult result = op.HandleAsyncResult(aResult);

                if (result != AsyncExecutionResult.Finished && op.IsCancellationRequested)
                {
                    result = AsyncExecutionResult.Cancelled;
                }

                if (result == AsyncExecutionResult.Executing || result == AsyncExecutionResult.WaitForPoll)
                {
                    result = op.TryExecuteIOUringAsync(_thread.ExecutionQueue, this, _keyForOperation);
                    Debug.Assert(result == AsyncExecutionResult.Executing);
                    return;
                }

                _executingOperation = null;

                AsyncOperation?next = CompleteOperationAndGetNext(op, result);

                if (next != null)
                {
                    ExecuteQueued(next);
                }
            }
Ejemplo n.º 3
0
            void IAsyncExecutionResultHandler.HandleAsyncResult(AsyncOperationResult aResult)
            {
                AsyncOperation?op = _executingOperation !;

                AsyncExecutionResult result = op.HandleAsyncResult(aResult);

                if (result != AsyncExecutionResult.Finished && op.IsCancellationRequested)
                {
                    result = AsyncExecutionResult.Cancelled;
                }

                if (result == AsyncExecutionResult.Executing)
                {
                    result = op.TryExecuteEpollAsync(triggeredByPoll: false, _thread.ExecutionQueue, this);
                    if (result == AsyncExecutionResult.Executing)
                    {
                        return;
                    }
                }

                _executingOperation = null;

                AsyncOperation?next = CompleteOperationAndGetNext(op, result);

                if (next != null)
                {
                    ExecuteQueued(triggeredByPoll: false, next);
                }
            }
Ejemplo n.º 4
0
            private AsyncOperation?CompleteOperationAndGetNext(AsyncOperation op, AsyncExecutionResult result)
            {
                if (result == AsyncExecutionResult.Finished)
                {
                    op.Status = OperationStatus.Completed;
                }
                else // AsyncExecutionResult.WaitForPoll or Cancelled
                {
                    if (result == AsyncExecutionResult.WaitForPoll)
                    {
                        OperationStatus previous = op.CompareExchangeStatus(OperationStatus.Queued, OperationStatus.Executing);
                        if (previous == OperationStatus.Executing)
                        {
                            // We've changed from executing to queued.
                            return(null);
                        }
                        Debug.Assert((previous & OperationStatus.CancellationRequested) != 0);
                    }
                    op.Status = (op.Status & ~(OperationStatus.CancellationRequested | OperationStatus.Executing)) | OperationStatus.Cancelled;
                }

                AsyncOperation?next = DequeueFirstAndGetNext(op);

                op.Complete();

                return(next);
            }
            public void ExecuteQueued(AsyncOperationResult asyncResult)
            {
                AsyncOperation?completedTail = null;

                lock (Gate)
                {
                    if (_tail is { } && _tail != AsyncOperation.DisposedSentinel)
 static void CompleteOperationsCancelled(ref AsyncOperation?tail)
 {
     while (TryQueueTakeFirst(ref tail, out AsyncOperation? op))
     {
         op.CompletionFlags = OperationCompletionFlags.CompletedCanceled;
         op.Complete();
     }
 }
Ejemplo n.º 7
0
        private AsyncOperation?_operation;  // for caching/cancelling.

        internal AsyncOperation StartReceiveOperation(Socket socket)
        {
            StartOperationCommon(socket, SocketAsyncOperation.Receive);
            var op = (_operation as SaeaReceiveOperation) ?? new SaeaReceiveOperation(this);

            op.Configure(socket, MemoryBuffer, BufferList);
            _operation = op;
            return(op);
        }
            public void ExecuteQueued(bool triggeredByPoll, AsyncOperationResult asyncResult)
            {
                AsyncOperation?completedTail = null;

                lock (Gate)
                {
                    _eventCounter++;

                    if (_tail is { } && _tail != AsyncOperation.DisposedSentinel)
Ejemplo n.º 9
0
        internal AsyncOperation StartConnectOperation(Socket socket)
        {
            StartOperationCommon(socket, SocketAsyncOperation.Connect);
            var op = (_operation as SaeaConnectOperation) ?? new SaeaConnectOperation(this);

            op.Configure(socket, RemoteEndPoint !);
            _operation = op;
            return(op);
        }
            private void CancelExecuting()
            {
                AsyncOperation?operation = Interlocked.Exchange(ref _cancellingOperation, null);

                if (operation?.IsCancellationRequested == true)
                {
                    _thread.ExecutionQueue.AddCancel(_context.Handle, _keyForOperation);
                }
            }
Ejemplo n.º 11
0
        internal AsyncOperation StartAcceptOperation(Socket socket)
        {
            StartOperationCommon(socket, SocketAsyncOperation.Accept);
            var op = (_operation as SaeaAcceptOperation) ?? new SaeaAcceptOperation(this);

            op.Configure(socket);
            _operation = op;
            return(op);
        }
Ejemplo n.º 12
0
        internal AsyncOperation StartSendOperation(Socket socket)
        {
            StartOperationCommon(socket, SocketAsyncOperation.Send);
            var           op     = (_operation as SaeaSendOperation) ?? new SaeaSendOperation(this);
            Memory <byte> buffer = MemoryBuffer.Slice(_offset, _count);

            op.Configure(socket, buffer, BufferList);
            _operation = op;
            return(op);
        }
Ejemplo n.º 13
0
        protected void RemoveQueued(AsyncOperation operation)
        {
            AsyncOperation?queue = Interlocked.CompareExchange(ref _queue, null, operation);

            if (object.ReferenceEquals(queue, operation))
            {
                return;
            }
            if (queue is object && IsGate(queue))
            {
                lock (queue)
                {
                    if (queue.Next == operation)         // We're the last
                    {
                        if (operation.Next == operation) // We're the only
                        {
                            queue.Next = null;           // empty
                        }
                        else
                        {
                            // Find newLast
                            AsyncOperation newLast = operation.Next !;
                            {
                                AsyncOperation newLastNext = newLast.Next !;
                                while (newLastNext != operation)
                                {
                                    newLast = newLastNext;
                                }
                            }
                            newLast.Next   = operation.Next; // last point to first
                            queue.Next     = newLast;        // gate points to last
                            operation.Next = operation;      // point to self
                        }
                    }
                    AsyncOperation?last = queue.Next;
                    if (last != null)
                    {
                        AsyncOperation it = last;
                        do
                        {
                            AsyncOperation next = it.Next !;
                            if (next == operation)
                            {
                                it.Next        = operation.Next; // skip operation
                                operation.Next = operation;      // point to self
                                return;
                            }
                            it = next;
                        } while (it != last);
                    }
                }
            }
        }
 protected static bool TryQueueTakeFirst(ref AsyncOperation?tail, [NotNullWhen(true)] out AsyncOperation?first)
 {
     first = tail?.Next;
     if (first != null)
     {
         QueueRemove(ref tail, first);
         return(true);
     }
     else
     {
         return(false);
     }
 }
        protected static void QueueAdd(ref AsyncOperation?tail, AsyncOperation operation)
        {
            Debug.Assert(operation.Next == null);
            operation.Next = operation;

            if (tail != null)
            {
                operation.Next = tail.Next;
                tail.Next      = operation;
            }

            tail = operation;
        }
Ejemplo n.º 16
0
        protected bool EnqueueAndGetIsFirst(AsyncOperation operation)
        {
            Debug.Assert(operation.Next == operation); // non-queued point to self.
            operation.Status = OperationStatus.Queued;
            AsyncOperation?queue = Interlocked.CompareExchange(ref _queue, operation, null);

            if (queue is null)
            {
                return(true);
            }

            return(EnqueueSlowAndGetIsFirst(operation, queue));
        }
            public bool Dispose()
            {
                AsyncOperation?queue = Interlocked.Exchange(ref _queue, DisposedSentinel);

                // already disposed
                if (queue == DisposedSentinel)
                {
                    return(false);
                }

                if (queue != null)
                {
                    AsyncOperation?gate = queue as AsyncOperationGate;
                    if (gate != null)
                    {
                        // Synchronize with Enqueue.
                        lock (gate)
                        { }

                        AsyncOperation?last = gate.Next;
                        if (last != null)
                        {
                            AsyncOperation op = gate.Next !;
                            do
                            {
                                AsyncOperation next = op.Next !;

                                op.Next = op; // point to self.
                                TryCancelAndComplete(op, OperationStatus.None, wait: true);

                                if (op == last)
                                {
                                    break;
                                }
                                op = next;
                            } while (true);
                        }
                    }
                    else
                    {
                        // queue is single operation
                        TryCancelAndComplete(queue, OperationStatus.None, wait: true);
                    }
                }

                return(true);
            }
        protected static bool QueueRemove(ref AsyncOperation?tail, AsyncOperation operation)
        {
            AsyncOperation?tail_ = tail;

            if (tail_ == null)
            {
                return(false);
            }

            if (tail_ == operation)
            {
                if (tail_.Next == operation)
                {
                    tail = null;
                }
                else
                {
                    AsyncOperation newTail     = tail_.Next !;
                    AsyncOperation newTailNext = newTail.Next !;
                    while (newTailNext != tail_)
                    {
                        newTail = newTailNext;
                    }
                    tail = newTail;
                }

                operation.Next = null;
                return(true);
            }
            else
            {
                AsyncOperation it = tail_;
                do
                {
                    AsyncOperation next = it.Next !;
                    if (next == operation)
                    {
                        it.Next        = next.Next;
                        operation.Next = null;
                        return(true);
                    }
                    it = next;
                } while (it != tail_);
            }

            return(false);
        }
Ejemplo n.º 19
0
            public void ExecuteQueued(bool triggeredByPoll, AsyncOperation?op = null)
            {
                if (triggeredByPoll)
                {
                    Interlocked.Increment(ref _eventCounter);
                }

                op ??= QueueGetFirst();
                do
                {
                    var spin = new SpinWait();
                    while (true)
                    {
                        if (op is null)
                        {
                            return;
                        }
                        OperationStatus previous = op.CompareExchangeStatus(OperationStatus.Executing, OperationStatus.Queued);
                        if (previous == OperationStatus.Queued)
                        {
                            // We've changed from queued to executing.
                            break;
                        }
                        else if ((previous & OperationStatus.Executing) != 0) // Also set when CancellationRequested.
                        {
                            // Already executing.
                            return;
                        }
                        // Operation was cancelled, but not yet removed from queue.
                        Debug.Assert((previous & OperationStatus.Cancelled) != 0);
                        spin.SpinOnce();
                        op = QueueGetFirst();
                    }

                    AsyncExecutionResult result = op.TryExecuteEpollAsync(triggeredByPoll, _thread.ExecutionQueue, this);

                    if (result == AsyncExecutionResult.Executing)
                    {
                        _executingOperation = op;
                        return;
                    }

                    op = CompleteOperationAndGetNext(op, result);
                } while (op != null);
            }
        // Requests cancellation of a queued operation.
        // If the operation is not on the queue (because it already completed), NotFound is returned.
        // If the operation is not executing, it is removed from the queue and Cancelled is returned.
        // If the operation is executing, it stays on the queue, the operation gets marked as cancellation requested,
        // and Requested is returned.
        protected CancellationRequestResult RequestCancellationAsync(AsyncOperation operation, OperationCompletionFlags flags)
        {
            CancellationRequestResult result = CancellationRequestResult.NotFound;

            if (_tail == operation) // We're the last operation
            {
                result = operation.RequestCancellationAsync(flags);
                if (result == CancellationRequestResult.Cancelled)
                {
                    if (operation.Next == operation) // We're the only operation.
                    {
                        _tail = null;
                    }
                    else
                    {
                        // Update tail
                        do
                        {
                            _tail = _tail.Next;
                        } while (_tail !.Next != operation);
                        // Update head
                        _tail.Next = operation.Next;
                    }
                    operation.Next = null;
                }
            }
            else if (_tail != null) // The list is multiple operations and we're not the last
            {
                ref AsyncOperation nextOperation = ref _tail.Next !;
                do
                {
                    if (nextOperation == operation)
                    {
                        result = operation.RequestCancellationAsync(flags);
                        if (result == CancellationRequestResult.Cancelled)
                        {
                            nextOperation  = operation.Next !;
                            operation.Next = null;
                        }
                        break;
                    }
                    nextOperation = ref nextOperation.Next !;
                } while (nextOperation != _tail);
            }
Ejemplo n.º 21
0
        public void RunWorkerAsync(object?argument)
        {
            if (_isRunning)
            {
                throw new InvalidOperationException(SR.BackgroundWorker_WorkerAlreadyRunning);
            }

            _isRunning           = true;
            _cancellationPending = false;

            _asyncOperation = AsyncOperationManager.CreateOperation(null);
            Task.Factory.StartNew(
                WorkerThreadStart,
                argument,
                CancellationToken.None,
                TaskCreationOptions.DenyChildAttach,
                TaskScheduler.Default
                );
        }
            private AsyncOperation?CompleteOperationAndGetNext(AsyncOperation op, AsyncExecutionResult result)
            {
                if (result == AsyncExecutionResult.Finished)
                {
                    op.Status = OperationStatus.Completed;
                }
                else // Cancelled
                {
                    op.Status = (op.Status & ~(OperationStatus.CancellationRequested | OperationStatus.Executing)) | OperationStatus.Cancelled;
                }

                Volatile.Write(ref _cancellingOperation, null);

                AsyncOperation?next = DequeueFirstAndGetNext(op);

                op.Complete();

                return(next);
            }
Ejemplo n.º 23
0
        protected AsyncOperation?QueueGetFirst()
        {
            AsyncOperation?queue = Volatile.Read(ref _queue);

            if (queue is null || IsDisposed(queue))
            {
                return(null);
            }
            if (IsGate(queue))
            {
                lock (queue)
                {
                    return(queue.Next?.Next);
                }
            }
            else
            {
                return(queue);
            }
        }
Ejemplo n.º 24
0
        internal void Complete(OperationStatus status)
        {
            bool cancelled      = (status & OperationStatus.Cancelled) != 0;
            bool completedAsync = (status & OperationStatus.Sync) == 0;

            if (cancelled)
            {
                SocketError = SocketError.OperationAborted;

                // We don't re-use operations that were cancelled async,
                // because cancellation is detected via StatusFlags.
                if (completedAsync)
                {
                    _operation = null;
                }
            }

            // Reset state.
            ExecutionContext?context = _context;

            _context         = null;
            CurrentSocket    = null;
            CurrentOperation = System.Net.Sockets.SocketAsyncOperation.None;

            // Call OnCompleted only when completed async.
            if (completedAsync)
            {
                if (context == null)
                {
                    OnCompleted(this);
                }
                else
                {
                    ExecutionContext.Run(context, s_executionCallback, this);
                }
            }
        }
 protected static AsyncOperation?QueueGetFirst(AsyncOperation?tail)
 => tail?.Next;
Ejemplo n.º 26
0
 internal AsyncOperation(AsyncOperation?preceeding, IAsyncOperator op)
 {
     Operator             = op;
     State                = AsyncOperationState.Initial;
     _preceedingOperation = preceeding;
 }
Ejemplo n.º 27
0
        protected bool EnqueueSlowAndGetIsFirst(AsyncOperation operation, AsyncOperation?queue)
        {
            Debug.Assert(queue != null);

            SpinWait spin = new SpinWait();

            while (true)
            {
                if (IsDisposed(queue))
                {
                    operation.Status = OperationStatus.None;
                    ThrowHelper.ThrowObjectDisposedException <AsyncContext>();
                }
                else
                {
                    // Install a gate.
                    if (!IsGate(queue))
                    {
                        AsyncOperation singleOperation = queue;
                        Debug.Assert(singleOperation.Next == singleOperation);

                        AsyncOperation gate = new AsyncOperationGate();
                        gate.Next = singleOperation;
                        queue     = Interlocked.CompareExchange(ref _queue, gate, singleOperation);
                        if (queue != singleOperation)
                        {
                            if (queue is null)
                            {
                                queue = Interlocked.CompareExchange(ref _queue, operation, null);
                                if (queue is null)
                                {
                                    return(true);
                                }
                            }
                            spin.SpinOnce();
                            continue;
                        }
                        queue = gate;
                    }

                    lock (queue)
                    {
                        if (object.ReferenceEquals(_queue, DisposedSentinel))
                        {
                            continue;
                        }

                        AsyncOperation?last = queue.Next;
                        if (last == null) // empty queue
                        {
                            queue.Next = operation;
                            return(true);
                        }
                        else
                        {
                            queue.Next     = operation; // gate points to new last
                            operation.Next = last.Next; // new last points to first
                            last.Next      = operation; // previous last points to new last
                            return(false);
                        }
                    }
                }
            }
        }
Ejemplo n.º 28
0
        public void SendAsync(MailMessage message, object?userToken)
        {
            ObjectDisposedException.ThrowIf(_disposed, this);


            try
            {
                if (InCall)
                {
                    throw new InvalidOperationException(SR.net_inasync);
                }

                if (message == null)
                {
                    throw new ArgumentNullException(nameof(message));
                }

                if (DeliveryMethod == SmtpDeliveryMethod.Network)
                {
                    CheckHostAndPort();
                }

                _recipients = new MailAddressCollection();

                if (message.From == null)
                {
                    throw new InvalidOperationException(SR.SmtpFromRequired);
                }

                if (message.To != null)
                {
                    foreach (MailAddress address in message.To)
                    {
                        _recipients.Add(address);
                    }
                }
                if (message.Bcc != null)
                {
                    foreach (MailAddress address in message.Bcc)
                    {
                        _recipients.Add(address);
                    }
                }
                if (message.CC != null)
                {
                    foreach (MailAddress address in message.CC)
                    {
                        _recipients.Add(address);
                    }
                }

                if (_recipients.Count == 0)
                {
                    throw new InvalidOperationException(SR.SmtpRecipientRequired);
                }

                InCall     = true;
                _cancelled = false;
                _message   = message;
                string?pickupDirectory = PickupDirectoryLocation;

                CredentialCache?cache;
                // Skip token capturing if no credentials are used or they don't include a default one.
                // Also do capture the token if ICredential is not of CredentialCache type so we don't know what the exact credential response will be.
                _transport.IdentityRequired = Credentials != null && (ReferenceEquals(Credentials, CredentialCache.DefaultNetworkCredentials) || (cache = Credentials as CredentialCache) == null || IsSystemNetworkCredentialInCache(cache));

                _asyncOp = AsyncOperationManager.CreateOperation(userToken);
                switch (DeliveryMethod)
                {
                case SmtpDeliveryMethod.PickupDirectoryFromIis:
                    throw new NotSupportedException(SR.SmtpGetIisPickupDirectoryNotSupported);

                case SmtpDeliveryMethod.SpecifiedPickupDirectory:
                {
                    if (EnableSsl)
                    {
                        throw new SmtpException(SR.SmtpPickupDirectoryDoesnotSupportSsl);
                    }

                    _writer = GetFileMailWriter(pickupDirectory);
                    bool allowUnicode = IsUnicodeSupported();
                    ValidateUnicodeRequirement(message, _recipients, allowUnicode);
                    message.Send(_writer, true, allowUnicode);

                    if (_writer != null)
                    {
                        _writer.Close();
                    }

                    AsyncCompletedEventArgs eventArgs = new AsyncCompletedEventArgs(null, false, _asyncOp.UserSuppliedState);
                    InCall = false;
                    _asyncOp.PostOperationCompleted(_onSendCompletedDelegate, eventArgs);
                    break;
                }

                case SmtpDeliveryMethod.Network:
                default:
                    _operationCompletedResult = new ContextAwareResult(_transport.IdentityRequired, true, null, this, s_contextSafeCompleteCallback);
                    lock (_operationCompletedResult.StartPostingAsyncOp())
                    {
                        if (NetEventSource.Log.IsEnabled())
                        {
                            NetEventSource.Info(this, $"Calling BeginConnect. Transport: {_transport}");
                        }
                        _transport.BeginGetConnection(_operationCompletedResult, ConnectCallback, _operationCompletedResult, Host !, Port);
                        _operationCompletedResult.FinishPostingAsyncOp();
                    }
                    break;
                }
            }
            catch (Exception e)
            {
                InCall = false;

                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Error(this, e);
                }

                if (e is SmtpFailedRecipientException && !((SmtpFailedRecipientException)e).fatal)
                {
                    throw;
                }

                Abort();

                if (e is SecurityException ||
                    e is AuthenticationException ||
                    e is SmtpException)
                {
                    throw;
                }

                throw new SmtpException(SR.SmtpSendMailFailure, e);
            }
        }