コード例 #1
0
            internal AsyncContext CreateContext(SafeHandle handle)
            {
                lock (_asyncContexts)
                {
                    if (_disposed)
                    {
                        ThrowHelper.ThrowObjectDisposedException <EPollThread>();
                    }

                    EPollAsyncContext context = new EPollAsyncContext(this, handle); // TODO: move this outside lock.

                    _asyncContexts.Add(context.Key, context);

                    return(context);
                }
            }
コード例 #2
0
            private unsafe void EventLoop()
            {
                try
                {
                    var eventBuffer = stackalloc epoll_event[EventBufferLength];
                    List <EPollAsyncContext?> asyncContextsForEvents = new List <EPollAsyncContext?>();

                    bool running      = true;
                    int  epollTimeout = -1;
                    while (running)
                    {
                        int rv = epoll_wait(_epollFd, eventBuffer, EventBufferLength, epollTimeout);
                        Volatile.Write(ref _blockedState, StateNotBlocked);

                        if (rv == -1)
                        {
                            if (LibC.errno == EINTR)
                            {
                                continue;
                            }

                            PlatformException.Throw();
                        }

                        lock (_asyncContexts)
                        {
                            for (int i = 0; i < rv; i++)
                            {
                                int key = eventBuffer[i].data.fd;
                                if (_asyncContexts.TryGetValue(key, out EPollAsyncContext? eventContext))
                                {
                                    asyncContextsForEvents.Add(eventContext);
                                }
                                else
                                {
                                    if (key == PipeKey)
                                    {
                                        running = !_disposed;
                                        ReadFromPipe(_asyncExecutionQueue);
                                    }
                                    asyncContextsForEvents.Add(null);
                                }
                            }
                        }

                        for (int i = 0; i < rv; i++)
                        {
                            EPollAsyncContext?context = asyncContextsForEvents[i];
                            if (context != null)
                            {
                                context.HandleEvents(eventBuffer[i].events);
                            }
                        }
                        asyncContextsForEvents.Clear();

                        bool actionsRemaining = false;

                        // Run this twice, executions cause more executions.
                        for (int i = 0; i < 2; i++)
                        {
                            // First execute scheduled actions, they can add to the exection queue.
                            ExecuteScheduledActions();
                            if (_asyncExecutionQueue != null)
                            {
                                actionsRemaining = _asyncExecutionQueue.ExecuteOperations();
                            }
                        }

                        if (!actionsRemaining)
                        {
                            // Check if there are scheduled actions remaining.
                            lock (_actionQueueGate)
                            {
                                actionsRemaining = _scheduledActions.Count > 0;
                                if (!actionsRemaining)
                                {
                                    Volatile.Write(ref _blockedState, StateBlocked);
                                }
                            }
                        }
                        epollTimeout = actionsRemaining ? 0 : -1;
                    }

                    // Execute actions that got posted before we were disposed.
                    ExecuteScheduledActions();

                    // Complete pending async operations.
                    _asyncExecutionQueue?.Dispose();

                    EPollAsyncContext[] contexts;
                    lock (_asyncContexts)
                    {
                        contexts = new EPollAsyncContext[_asyncContexts.Count];
                        _asyncContexts.Values.CopyTo(contexts, 0);
                        _asyncContexts.Clear();
                    }
                    foreach (var context in contexts)
                    {
                        context.Dispose();
                    }

                    FreeResources();
                }
                catch (Exception e)
                {
                    Environment.FailFast(e.ToString());
                }
            }