Передача сообщений между потоками с использованием командного файла

0

Этот проект попросил 4 потока, которые имеют командный файл с инструкциями, такими как SEND, Receive и quit. Когда файл говорит "2 отправить", поток, который на втором месте в массиве должен просыпаться и получать его сообщение. Мне нужно знать, как сделать поток, прочитав это сообщение, если для файла команды есть сообщение для него?

  • 0
    Есть ли преимущество использования pthreads перед библиотекой потоков C ++ 11?
  • 1
    А? Конечно, это действительно ненормальный способ обработки IPC?
Показать ещё 1 комментарий
Теги:
multithreading
message-passing

1 ответ

1
Лучший ответ

Самая большая проблема, которую я вижу для вашего проекта, состоит в том, что каждый поток читает свою строку случайным образом независимо от любого другого потока. После этого ему нужно будет проверить, действительно ли текущая строка предназначена для него, т.е. начиная с соответствующего номера. Что произойдет, если нет? Слишком сложно.

Я бы разделил эту проблему на один поток читателей и набор рабочих потоков. Первый считывает строки из файла и отправляет их рабочим, нажимая их в текущую очередь рабочих. Все синхронизированы с рабочим мьютеком и условной переменной. В С++ 11 реализовано следующее, но также должно выполняться в стиле pthread_ *.

#include <thread> 
#include <iostream> 
#include <queue> 
#include <mutex> 
#include <fstream> 
#include <list> 
#include <sstream> 
#include <condition_variable> 

class worker  { 
public: 
    void operator()(int n) { 
        while(true) { 
            std::unique_lock<std::mutex> l(_m); 
            _c.wait(l); 
            if(!_q.empty()) { 
                { 
                    std::unique_lock<std::mutex> l(_mm); 
                    std::cerr << "#" << n << " " << _q.back() <<std::endl; 
                } 
                _q.pop(); 
            } 
        } 
    } 
private: 
    std::mutex              _m; 
    std::condition_variable _c; 
    std::queue<std::string> _q; 
    //  Only needed to synchronize I/O 
    static std::mutex       _mm; 
    // Reader may write into our queue 
    friend class reader; 
}; 

std::mutex       worker::_mm; 

class reader  { 
public: 
    reader(worker & w0,worker & w1,worker & w2,worker & w3) { 
        _v.push_back(&w0); 
        _v.push_back(&w1); 
        _v.push_back(&w2); 
        _v.push_back(&w3); 
    } 
    void operator()() { 
        std::ifstream fi("commands.txt"); 
        std::string s; 

        while(std::getline(fi,s)) { 
            std::stringstream ss(s); 
            int n; 
            if((ss >> n >> std::ws) && n>=0 && n<_v.size()) { 
                std::string s0; 
                if(std::getline(ss,s0)) { 
                    std::unique_lock<std::mutex> l(_v[n]->_m); 
                    _v[n]->_q.push(s0); 
                    _v[n]->_c.notify_one(); 
                } 
            } 
        } 

        std::cerr << "done" << std::endl; 
    } 
private: 
    std::vector<worker *> _v; 

}; 

int main(int c,char **argv) { 

    worker w0; 
    worker w1; 
    worker w2; 
    worker w3; 

    std::thread tw0([&w0]() { w0(0); }); 
    std::thread tw1([&w1]() { w1(1); }); 
    std::thread tw2([&w2]() { w2(2); }); 
    std::thread tw3([&w3]() { w3(3); }); 

    reader r(w0,w1,w2,w3); 

    std::thread tr([&r]() { r(); }); 

    tr.join(); 
    tw0.join(); 
    tw1.join(); 
    tw2.join(); 
    tw3.join(); 
} 

Код примера читается только с "commands.txt" до EOF. Я предполагаю, что вы хотели бы постоянно читать, как команда "tail -f". Это, однако, невозможно для std :: istream.

Код, конечно, неуклюжий, но я думаю, это дает вам представление. Например, следует добавить механизм блокировки, если рабочие слишком медленно обрабатывают свой материал, и очереди могут съесть всю драгоценную RAM.

  • 1
    «Например, следует добавить механизм блокировки, если рабочие слишком медленно обрабатывают свои вещи и очереди могут съесть всю драгоценную оперативную память». Звучит как работа для параллельной ограниченной очереди TBB
  • 0
    @sjdowling выглядит хорошо для меня.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню