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);
                }
            }
            public void ExecuteQueued(AsyncOperationResult asyncResult)
            {
                AsyncOperation?completedTail = null;

                lock (Gate)
                {
                    if (_tail is { } && _tail != AsyncOperation.DisposedSentinel)
 void IAsyncExecutionResultHandler.HandleAsyncResult(AsyncOperationResult result)
 {
     if (result.IsError && result.Errno != EAGAIN)
     {
         PlatformException.Throw();
     }
 }
Exemplo n.º 4
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);
                }
            }
            public void ExecuteQueued(bool triggeredByPoll, AsyncOperationResult asyncResult)
            {
                AsyncOperation?completedTail = null;

                lock (Gate)
                {
                    _eventCounter++;

                    if (_tail is { } && _tail != AsyncOperation.DisposedSentinel)
 void IAsyncExecutionResultHandler.HandleAsyncResult(AsyncOperationResult asyncResult)
 {
     // TODO: do we need to do a volatile read of _disposed?
     if (asyncResult.Errno == EAGAIN || (!asyncResult.IsError && asyncResult.Value == 8))
     {
         AddReadFromEventFd();
     }
     else if (asyncResult.IsError)
     {
         PlatformException.Throw(asyncResult.Errno);
     }
     else
     {
         ThrowHelper.ThrowIndexOutOfRange(asyncResult.Value);
     }
 }
Exemplo n.º 7
0
 public override AsyncExecutionResult HandleAsyncResult(AsyncOperationResult result)
 => throw new System.InvalidOperationException();
Exemplo n.º 8
0
            public unsafe bool ExecuteOperations()
            {
                List <Operation>?scheduled = _scheduledOperations;

                if (scheduled == null)
                {
                    return(false);
                }
                _scheduledOperations  = _cachedOperationsList;
                _cachedOperationsList = null;

                if (_results == null || _results.Length < scheduled.Count)
                {
                    _results = new AsyncOperationResult[Math.Max(scheduled.Count, 2 * (_results?.Length ?? 0))];
                }
                AsyncOperationResult[] results = _results;

                int queueLength = scheduled.Count;
                int queueOffset = 0;

                while (queueOffset < queueLength)
                {
                    int nr = Math.Min((queueLength - queueOffset), IocbLength);
                    try
                    {
                        iocb *aioCbs = AioCbs;
                        for (int i = queueOffset; i < (queueOffset + nr); i++)
                        {
                            Operation op = scheduled[i];
                            int       fd = op.Handle.DangerousGetHandle().ToInt32(); // TODO: make safe

                            MemoryHandle handle = op.Memory.Pin();
                            _memoryHandles.Add(handle);

                            aioCbs->aio_fildes     = fd;
                            aioCbs->aio_data       = (ulong)i;
                            aioCbs->aio_lio_opcode = op.IsReadNotWrite ? IOCB_CMD_PREAD : IOCB_CMD_PWRITE;
                            aioCbs->aio_buf        = (ulong)handle.Pointer;
                            aioCbs->aio_nbytes     = (ulong)op.Memory.Length;
                            aioCbs++;
                        }
                        iocb **iocbpp   = AioCbsTable;
                        int    toSubmit = nr;
                        while (toSubmit > 0)
                        {
                            int rv = io_submit(_ctx, toSubmit, iocbpp);
                            if (rv == -1)
                            {
                                PlatformException.Throw();
                            }
                            int toReceive = rv;
                            toSubmit -= rv;
                            iocbpp   += rv;
                            while (toReceive > 0)
                            {
                                do
                                {
                                    rv = IoGetEvents(_ctx, toReceive, AioEvents);
                                } while (rv == -1 && errno == EINTR);
                                if (rv == -1)
                                {
                                    PlatformException.Throw();
                                }
                                io_event *events = AioEvents;
                                for (int i = 0; i < rv; i++)
                                {
                                    results[(int)events->data] = new AsyncOperationResult(events->res);
                                    events++;
                                }
                                toReceive -= rv;
                            }
                        }
                    }
                    finally
                    {
                        foreach (var handle in _memoryHandles)
                        {
                            handle.Dispose();
                        }
                        _memoryHandles.Clear();
                    }

                    // Callbacks
                    for (int i = queueOffset; i < (queueOffset + nr); i++)
                    {
                        Operation op = scheduled[i];
                        op.Callback(results[i], op.State, op.Data);
                    }

                    queueOffset += nr;
                }

                scheduled.Clear();
                if (_scheduledOperations == null)
                {
                    _scheduledOperations = scheduled;
                    return(false);
                }
                else
                {
                    _cachedOperationsList = scheduled;
                    return(_scheduledOperations.Count > 0);
                }
            }
Exemplo n.º 9
0
 // Continues execution of this operation.
 // When the operation is finished, AsyncExecutionResult.Finished is returned.
 // The executionQueue, when not null, can be used to batch operations.
 //   The callback, state, and data arguments must be passed on to the executionQueue.
 // When the executionQueue is used, AsyncExecutionResult.Executing is returned.
 // When the batched operations completes, the method is called again and 'result' has a value.
 // The execution queue may or may not support poll operations (ExecutionQueue.SupportsPolling).
 // In case there is no execution queue, or the queue does not support polling, the method
 // can return WaitForPoll. The method will be called again when poll indicates the handle is ready,
 // (and triggeredByPoll is true).
 // When asyncOnly is set, the execution queue must be used. If it cannot be used, WaitForPoll
 // must be returned.
 // When cancellationRequested is set, the operation must finish with
 //   AsyncExecutionResult.Finished when the operation completed using 'result'; and
 //   AsyncOperationResult.Cancelled otherwise.
 public abstract AsyncExecutionResult TryExecute(bool triggeredByPoll, bool cancellationRequested, bool asyncOnly, AsyncExecutionQueue?executionQueue, AsyncExecutionCallback?callback, object?state, int data, AsyncOperationResult result);
Exemplo n.º 10
0
 public override AsyncExecutionResult TryExecute(bool triggeredByPoll, bool cancellationRequested, bool asyncOnly, AsyncExecutionQueue?executionQueue, AsyncExecutionCallback?callback, object?state, int data, AsyncOperationResult result)
 => throw new System.InvalidOperationException();