Как эффективно передать аргумент, который встречается очень редко, дочернему потоку? - PullRequest
0 голосов
/ 25 июня 2018

Я хотел бы передать строковый аргумент в дочерний поток (который постоянно читает сокет) и вызвать setsockopt() с этим аргументом в этом сокете.

Я использую сокеты ZeroMQ,поэтому вызов setsockopt() - это , а не threadsafe здесь, я бы назвал setsockopt() из дочернего потока (как было рекомендовано здесь ).Обновление аргумента могло бы произойти, вероятно, только один раз в миллиардах циклов чтения, и было бы немного неправильно добавлять if -структуру к каждому циклу ребенка следующим образом:

bool new_arg_available;
std::string new_arg;

while(1){
    sub_socket->recv(data);   // . . . . . . a blocking method call
    printData(data)

    ...                       // . . . . . . data can set new_arg_available

    if (new_arg_available){   // . . . . . . synchronization goes here
        sub_socket->setsockopt(ZMQ_SUBSCRIBE, new_arg, ... );
        new_arg_available = false;
    }
}

Для меня наиболееЭто может быть просто:

  1. Добавить мьютекс в глобальное пространство имен, заблокировать его, когда new_arg доступно в родительском потоке, и разблокировать его из дочернего потока.

  2. используйте std::atomic<bool> и используйте его так же, как в 1.

Однако чего-то, чего я хотел бы достичь, так это заставить ребенкапрерванный, чтобы я мог устранить структуру if с конца блока while(){...}.Я бы не отказался от штрафа за переключение контекста, потому что это событие было бы очень редко.

Я относительно новичок в C ++, и я хотел бы узнать здесь о лучших практиках, как этого добиться вэффективный способ.Я хотел бы решить эту проблему, не используя Boost, единственные примеры, которые я смог найти для достижения прерываемых потоков, - это использование Boost.

1 Ответ

0 голосов
/ 25 июня 2018

Добро пожаловать в страну Zen-of-Zero

Основное замечание о евангелизации ZeroMQ заключается в том, что авторы ZeroMQ с тех пор выступали за избегание какого-либо обмена - Ноль-sharing.

Учитывая, что вы уже создали экземпляр инфраструктуры ZeroMQ, лучше использовать межпотоковый PUSH/PULL через транспорт без IO-потока inproc://-класс и забудьте о любой хитрой (b-) блокировке.

Одна сторона (Инжектор) просто aPushCHANNEL.send( new_arg );
, а другая (Реализатор) просто либо aPullCHANNEL.recv() -s при необходимости / при необходимости, или может использовать более умные средства тестирования aPullCHANNEL.poll(), опять же, лучше всего, если использовать форму нулевого ожидания в опросе if aPullCHANNEL.poll( 0 ){...}else{...}

И ваш архитектура становится полностью разложенной, основанной на ролях, многоагентной, чистой и умной, без каких-либо грязных взаимоблокировок (поэтому лучше всего забыть REQ/REP с самого начала), без каких-либо трудных для отслеживания / отладки концептуальных ошибок и всех ошибокобнаружено где приложениеи где местная ответственность имеет смысл отобразить первопричину любой такой ошибки для оперативной обработки ошибок.


NB: Да, ZeroMQс тех пор когда-либо разрабатывался без необходимости обеспечения безопасности потоков, так как не было ничего общего для совместного использования (совместное использование нуля).Некоторые недавние усилия в API v4.1 + начали отклоняться от этого Zen-of-Zero, поэтому можно прочитать о некоторых аспектах безопасности потоков, но, как отмечалось выше, и присутствовать почти на каждой странице невероятного ZeroMQ Pieter HINTJENS '.Библейская книга - " Код подключен, том 1 " - лучше всего ничего не делить.

Конструкция ZeroMQ полностью асинхронна и не требует ухода за блокировками, мьютекс-гимнастикой и другими внешне введенными формами.элементы в чистой и умной многоагентной архитектуре асинхронной сигнализации / обмена сообщениями на основе .Вы влюбитесь в него, поэтому продолжайте пробовать и читайте книгу.Это будет трудно, но заплатит много за тех, кто продолжит и найдет красоту ZeroMQ Zen-of-Zero.

...