2012-06-30 4 views
1

Имея несколько процессов, все записи в одном и том же потоке вывода (например, с std::cout), есть способ заблокировать поток, чтобы, когда процесс начал писать собственное сообщение, он может сделать это до конца (например, с std::endl)?Блокировка выходного потока для многопроцессорной синхронизации?

Мне нужен переносной способ сделать это.

+1

Это может не соответствовать параметрам вашей ситуации, но вы можете потенциально перетащить все данные в отдельный рабочий процесс, который агрегирует данные (с собственной внутренней блокировкой), прежде чем сбрасывать их на стандартный вывод. – reuben

+0

@reuben: в моем случае ваше решение является лучшим. Если вы напишете ответ, я могу выбрать его как принятый. – Pietro

ответ

2

Непонятно, подходит ли оно для параметров вашей ситуации, но вы могли бы поместить все данные в отдельный рабочий процесс, который агрегирует данные (с его собственной внутренней блокировкой), прежде чем сбрасывать их на стандартный вывод.

2

Вам не повезло. Вам придется использовать все, что предоставляет ваша система такетов. Это означает использование глобальных/общесистемных мьютексов или lockf() подобных функций. Вы можете использовать некоторую стороннюю библиотеку для удовлетворения требований к переносимости, например Boost.Interprocess.

+0

Знаете ли вы, есть ли что-нибудь подобное в C++ 11? – Pietro

+0

@Pietro: Я так не думаю. – wilx

1

Если вы используете ОС UNIX, то вы можете имитировать поведение, которое вы хотите, с помощью адаптера stringstream. Это может быть не лучший способ его выполнить, но идея состоит в том, чтобы вызвать один вызов write, когда встречается std::endl.

// Assume fd is in blocking mode 
class fdostream : public std::ostringstream { 
    typedef std::ostream & (*manip_t) (std::ostream &); 
    struct fdbuf : public std::stringbuf { 
     int fd_; 
     fdbuf (int fd) : fd_(fd) {} 
     int sync() { 
      int r = ::write(fd_, str().data(), str().size()); 
      str(std::string()); 
      return (r > 0) ? 0 : -1; 
     } 
    } buf_; 
    std::ostream & os() { return *this; } 
public: 
    fdostream (int fd) : buf_(fd) { os().rdbuf(&buf_); } 
}; 

fdostream my_cout(1); 
my_cout << "Hello," << " world!" << std::endl; 

Это должно достичь эффекта синхронизированных записи, за счет ввода буферизации в stringstream, а затем очищая внутреннюю string после каждой промывки.

Для большей переносимости вы можете изменить код для использования fwrite и указать небуферизованные записи с помощью setvbuf. Но атомарность fwrite будет зависеть от реализации библиотеки библиотеки.

Смежные вопросы