Спящий рабочий stream на файловом сервере

Я реализую файловый сервер и получает запросы от нескольких клиентов. Каждый клиент отправляет несколько запросов. На конце сервера основной stream генерирует новый рабочий stream для обработки запросов каждый раз, когда подключается новый клиент. Один рабочий stream обрабатывает все запросы от клиента, для которого он был создан. Таким образом, после того, как stream обрабатывает запросы, он ожидает, что его разбудит основной stream, когда придет другой запрос от того же клиента.

Я не уверен, как реализовать последнюю строку. Именно так я помещаю stream спать и снова разбужу его.

Спасибо

    Использовать переменные условия https://computing.llnl.gov/tutorials/pthreads/#ConVarSignal

    Вы не «ставите нить спать». Поток будет спать, когда он сделает любой системный вызов блокировки.

    Существует много способов реализовать то, что вы описываете, наиболее распространенным, возможно, является «шаблон пула streamов» . Обычно это выполняется с использованием streamовой очереди, которая, в свою очередь, может быть реализована с помощью мьютексов и переменных условий.

    Рабочий stream засыпает, когда он ждет переменную условия (pthread_cond_wait), и мастер разбудит ее, сигнализируя переменную условия (pthread_cond_signal).

    Небольшой поиск должен привести к появлению ряда примеров кода на основе pthread для очередей.

    Поддерживает ли ваши клиентские streamи какие-либо состояния для клиента? Если это так, я могу понять, зачем вам нужен один выделенный stream для каждого клиента. Если это так, вы можете использовать очередь производителей-потребителей для каждого streamа клиентского обработчика, как предложено Cnicutar и другими плакатами. Обычно я использую семафорный togehter с мьютексом, поскольку такой синхр доступен на всех платформах, но condvars OK. Неясно, как вы идентифицируете клиента при входе в файл, поэтому управление streamами клиентов может быть неудобным или нет. Когда в основной stream входит запрос файла, как вы знаете, в какую очередь его нажать?

    Rgds, Martin

    Вы должны изучить проблему производителей-потребителей. В двух словах вы хотите сделать что-то вроде этого:

    • Рабочий stream пытается получить «задание» из очереди
    • Если очередь пуста, stream блокирует (семафор / переменная условия), в противном случае он получает задание и обрабатывает его
    • Мастер-очередь помещает задания в очереди и уведомляет рабочих («эй, там есть работа»)
    • Оповещенный работник мгновенно просыпается и пытается получить работу из очереди

    Хитрость заключается в том, чтобы сделать это по-настоящему элегантным:

    • get должен автоматически блокироваться, когда очередь пуста
    • put должен автоматически сигнализировать работникам, ожидающим на нем

    Как бы вы это сделали с тем, что Linux предоставляет вам?

    • sempahores
    • переменные условия pthreads

    Теперь вернемся к вашему вопросу. Кажется немного сомнительным, что вы начинаете stream для каждого клиента. Было бы проще, если бы у вас мог быть пул streamов, который сидел и обрабатывал запросы от любого клиента.

    Я решил проблему streamами, созданными в начале подключения клиента, и после этого stream получает и отправляет сообщения непосредственно клиенту, а не основной stream, получающий и отправляющий сообщения после того, как рабочие streamи выполняют задачу.

    У вас есть несколько возможностей, но я реализовал аналогичное многопоточное решение следующим образом:

    • Разрешить возвращать метод рабочего streamа, когда он не работает
    • Когда ваш родительский stream получает запрос, добавьте его в очередь рабочего streamа и вызовите метод «Wakeup» в соответствии с:

       private void Wakeup() { if (!_workerThread.IsBusy) _workerThread.RunWorkerAsync(); } 

    Это позволит вам не иметь зависание вашего streamа в состоянии сна, где ему необходимо регулярно проверять, было ли запрошено пробуждение. Это ставит задачу просыпать рабочий stream на родительский stream.