Tôi đang viết một máy chủ đa luồng tương thích POSIX trong c/C++ phải có khả năng chấp nhận, đọc từ và ghi vào một số lượng lớn kết nối không đồng bộ. Máy chủ có một số luồng công nhân thực hiện nhiệm vụ và đôi khi (và không thể đoán trước) dữ liệu hàng đợi được ghi vào ổ cắm. Dữ liệu cũng đôi khi (và không thể đoán trước) được ghi vào ổ cắm bởi các máy khách, vì vậy máy chủ cũng phải đọc không đồng bộ. Một cách rõ ràng để làm điều này là cung cấp cho mỗi kết nối một luồng mà đọc và ghi từ/đến socket của nó; điều này là xấu, mặc dù, vì mỗi kết nối có thể tồn tại trong một thời gian dài và máy chủ do đó có thể phải giữ hàng trăm hoặc hàng ngàn chủ đề chỉ để theo dõi các kết nối.Đang chờ điều kiện (pthread_cond_wait) và thay đổi ổ cắm (chọn) đồng thời
Một cách tiếp cận tốt hơn là phải có một chuỗi duy nhất xử lý tất cả các liên lạc bằng cách sử dụng các hàm select()/pselect(). Tức là, một chuỗi đơn lẻ chờ trên bất kỳ socket nào có thể đọc được, sau đó sinh ra một công việc để xử lý đầu vào sẽ được xử lý bởi một nhóm các chủ đề khác bất cứ khi nào đầu vào có sẵn. Bất cứ khi nào các luồng công nhân khác tạo ra đầu ra cho một kết nối, nó sẽ được xếp hàng đợi và luồng giao tiếp đợi cho socket đó có thể ghi được trước khi ghi nó.
Vấn đề với điều này là luồng giao tiếp có thể đang chờ trong hàm select() hoặc pselect() khi đầu ra được xếp hàng đợi bởi các luồng công nhân của máy chủ. Có thể, nếu không có đầu vào đến trong vài giây hoặc vài phút, một đoạn đầu ra được xếp hàng đợi sẽ chỉ đợi cho chuỗi giao tiếp được thực hiện select() ing. Điều này không nên xảy ra, tuy nhiên - dữ liệu nên được viết càng sớm càng tốt.
Hiện tại tôi thấy một vài giải pháp cho vấn đề này an toàn chỉ. Một là để có các chủ đề giao tiếp bận rộn-chờ đợi trên đầu vào và cập nhật danh sách các ổ cắm nó chờ đợi để viết mỗi thứ mười của một giây hoặc lâu hơn. Đây không phải là tối ưu vì nó liên quan đến việc chờ đợi, nhưng nó sẽ hoạt động. Một tùy chọn khác là sử dụng pselect() và gửi tín hiệu USR1 (hoặc một cái gì đó tương đương) bất cứ khi nào đầu ra mới được xếp hàng đợi, cho phép chuỗi giao tiếp cập nhật danh sách các ổ cắm mà nó đang chờ trạng thái ghi ngay lập tức. Tôi thích thứ hai ở đây, nhưng vẫn không thích sử dụng một tín hiệu cho một cái gì đó mà phải là một điều kiện (pthread_cond_t). Tuy nhiên, một tùy chọn khác sẽ bao gồm, trong danh sách các bộ mô tả tập tin mà select() đang đợi, một tệp giả mà chúng ta viết một byte vào bất cứ khi nào một socket cần được thêm vào tập tin fd_set có thể ghi cho select(); điều này sẽ đánh thức máy chủ truyền thông vì tệp giả định cụ thể đó sẽ có thể đọc được, do đó cho phép luồng truyền thông cập nhật ngay lập tức fd_set có thể ghi.
Tôi cảm thấy một cách trực quan, cách tiếp cận thứ hai (với tín hiệu) là cách 'chính xác nhất' để lập trình máy chủ, nhưng tôi tò mò nếu có ai biết điều nào ở trên là hiệu quả nhất, nói chung, cho dù một trong những điều trên sẽ gây ra điều kiện chủng tộc mà tôi không biết, hoặc nếu có ai biết về một giải pháp chung chung hơn cho vấn đề này. Những gì tôi thực sự muốn là một hàm pthread_cond_wait_and_select() cho phép thread comm đợi cả hai thay đổi trong socket hoặc tín hiệu từ một điều kiện.
Xin cảm ơn trước.