Этот проект попросил 4 потока, который имеет командный файл с
инструкции, такие как ОТПРАВИТЬ, Получить и выйти. Когда в файле написано «2
отправить «поток, который на втором месте в массиве должен проснуться
и получить свое сообщение. Мне нужно знать, как заставить поток читать
это сообщение, если в командном файле есть сообщение для него?
Самая большая проблема, которую я вижу для вашего дизайна, заключается в том, что каждый поток читает свою строку случайным образом независимо от любого другого потока. После этого он должен будет проверить, предназначена ли для него текущая строка, т. Е. Начиная с соответствующего номера. Что будет, если нет? Слишком сложно.
Я бы разделил этот вопрос на один читатель нить и набор работник потоки. Первый читает строки из файла и отправляет его рабочим, помещая его в текущую очередь рабочих. Все синхронизировано с мьютексом и условной переменной на каждого работника. Следующее реализовано в C ++ 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.
Код, конечно, неуклюжий, но я думаю, он дает вам представление. Например, следует добавить механизм блокировки, если рабочие слишком медленно обрабатывают свои вещи и очереди могут поглотить всю драгоценную оперативную память.