public TransportThread(IPEndPoint endPoint, IConnectionDispatcher connectionDispatcher, LinuxTransportOptions options, AcceptThread acceptThread, int threadId, int cpuId, ILoggerFactory loggerFactory) { if (connectionDispatcher == null) { throw new ArgumentNullException(nameof(connectionDispatcher)); } ConnectionDispatcher = connectionDispatcher; ThreadId = threadId; CpuId = cpuId; EndPoint = endPoint; TransportOptions = options; AcceptThread = acceptThread; LoggerFactory = loggerFactory; }
private TransportThread[] CreateTransportThreads(IPEndPoint ipEndPoint, AcceptThread acceptThread) { var threads = new TransportThread[_transportOptions.ThreadCount]; IList <int> preferredCpuIds = null; if (_transportOptions.SetThreadAffinity) { preferredCpuIds = GetPreferredCpuIds(); } int cpuIdx = 0; for (int i = 0; i < _transportOptions.ThreadCount; i++) { int cpuId = preferredCpuIds == null ? -1 : preferredCpuIds[cpuIdx++ % preferredCpuIds.Count]; int threadId = Interlocked.Increment(ref s_threadId); var thread = new TransportThread(ipEndPoint, _connectionDispatcher, _transportOptions, acceptThread, threadId, cpuId, _loggerFactory); threads[i] = thread; } return(threads); }
public async Task BindAsync() { AcceptThread acceptThread; TransportThread[] transportThreads; lock (_gate) { if (_state != State.Created) { ThrowInvalidOperation(); } _state = State.Binding; IPEndPoint ipEndPoint; switch (_endPoint.Type) { case ListenType.IPEndPoint: ipEndPoint = _endPoint.IPEndPoint; acceptThread = null; transportThreads = CreateTransportThreads(ipEndPoint, acceptThread); break; case ListenType.SocketPath: case ListenType.FileHandle: Socket socket; if (_endPoint.Type == ListenType.SocketPath) { socket = Socket.Create(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified, blocking: false); File.Delete(_endPoint.SocketPath); socket.Bind(_endPoint.SocketPath); socket.Listen(ListenBacklog); } else { socket = new Socket((int)_endPoint.FileHandle); } ipEndPoint = null; acceptThread = new AcceptThread(socket); transportThreads = CreateTransportThreads(ipEndPoint, acceptThread); break; default: throw new NotSupportedException($"Unknown ListenType: {_endPoint.Type}."); } _threads = new ITransportActionHandler[transportThreads.Length + (acceptThread != null ? 1 : 0)]; _threads[0] = acceptThread; for (int i = 0; i < transportThreads.Length; i++) { _threads[i + (acceptThread == null ? 0 : 1)] = transportThreads[i]; } _logger.LogDebug($@"BindAsync {_endPoint}: TC:{_transportOptions.ThreadCount} TA:{_transportOptions.SetThreadAffinity} IC:{_transportOptions.ReceiveOnIncomingCpu} DA:{_transportOptions.DeferAccept}"); } var tasks = new Task[transportThreads.Length]; for (int i = 0; i < transportThreads.Length; i++) { tasks[i] = transportThreads[i].BindAsync(); } try { await Task.WhenAll(tasks); if (acceptThread != null) { await acceptThread.BindAsync(); } lock (_gate) { if (_state == State.Binding) { _state = State.Bound; } else { ThrowInvalidOperation(); } } } catch { await StopAsync(); throw; } }