2010-03-21 6 views
7

У меня есть цикл, который в основном вызывает это каждые несколько секунд (после тайм-аута):вспыхивают из гнезда выберите

while(true){ 

    if(finished) 
     return; 

    switch(select(FD_SETSIZE, &readfds, 0, 0, &tv)){ 
     case SOCKET_ERROR : report bad stuff etc; return; 
     default : break; 
    } 

    // do stuff with the incoming connection 
} 

Так в основном за каждые несколько секунд (что определяется ТВ), он активирует прослушивание ,

Это выполняется на резьбе B (не основной нить). Есть моменты, когда я хочу закончить этот акцепторный цикл сразу из потока A (основной поток), но похоже, что мне нужно подождать, пока промежуток времени не закончится.

Есть ли способ нарушить функцию выбора из другого потока поэтому поток B может немедленно прекратиться?

+0

Sidenote: вы можете вырезать if-инструкцию и просто написать while (! Finished). –

+0

Это займет 100% процессорного времени. Определенно не приемлемо. – kamziro

+0

Крики, я, должно быть, неправильно понял, что – kamziro

ответ

9

Самый простой способ - это, вероятно, использовать pipe(2) для создания трубы и добавления считываемого конца в readfds. Когда другой поток хочет прервать select(), просто напишите ему байт, а затем уничтожьте его потом.

+0

Это сокет-слушатель (тот, который принимает соединения). Будет ли это работать? Я думал о вызове функции, которая разрушает сокет. Чтобы узнать, что произойдет. Будет ли это безопасно? – kamziro

+1

Ожидает * файла *. Это не волнует, что *, он просто хочет * что-то *. –

+0

Это сработало, и я узнал кое-что с Unix-трубами! Благодаря! Кстати, все, что я делаю после прерывания, - это выход из программы. поэтому я не беспокоюсь о потреблении. Все в порядке? – kamziro

3

Да, вы создаете подключенную пару разъемов. Затем поток B записывает на одну сторону сокета и поток A добавляет другой боковой сокет для выбора. Поэтому, как только B пишет в сокет A, выйдите из выбора, не забудьте прочитать этот байт из сокета.

Это самый стандартный и распространенный способ прерывания выбора.

Примечание:

Под Unix, используйте socketpair для создания пары сокетов, под окнами это немного сложно, но прибегая к помощи Windows, socketpair даст вам образцы кода.

+0

Ах, я просто использовал трубку (2) и, похоже, работает , Возможно, мне придется беспокоиться о его оконном коллеге в конце концов. – kamziro

-1

Не можете ли вы просто сделать тайм-аут достаточно коротким (например, 10 мсек?).

Это решение типа «просто создать фиктивное соединение» вроде как взломанное. Я лично считаю, что если приложение хорошо спроектировано, одновременные задачи никогда не должны прерываться принудительно, просто проверка работника достаточно часто (это также является причиной того, что boost.threads не имеет функции завершения).

Редактировать Сделал этот ответ CV. Это плохо, но это может помочь другим понять, почему это плохо, что объясняется в комментариях.

+1

-1 Это очень плохое решение, которое просто стоит CPU и все еще имеет проблемы с задержкой. Для этого существуют стандартные решения. – Artyom

+0

Как это стоит CPU? Что такое 10 мс ожидания процессора по сравнению с созданием фиктивного соединения сокета? –

+1

Стоимость процессора сводится к сокращению времени ожидания, что делает цикл более частым. – caf

-1

Вы можете использовать вызов выключения (Sock, SHUT_RDWR) из основного потока, чтобы выйти из ожидающего вызова вызова, который также выйдет из другого потока до истечения таймаута, поэтому вам не нужно ждать окончания истечения времени ожидания.

ура. :)

+1

К сожалению, вы не можете отключить прослушивание. И нет безопасного способа «закрыть» его, пока другой поток, или, возможно, его использует. –

+0

Если у вас есть функция потока сокетов, упомянутая ниже, и если вы отправляете shutdown (sock, SHUT_RD) из основного потока, он будет ожидать ожидающего вызова выбора из SockThreadFunction, выполняющегося в другом потоке. Я пробовал это и работаю хорошо. SockThreadFunction() {while (SocketOpen) {// Ожидание выбора вызова int Ready = select (pSocket-> m_Sock + 1, & SockSet, 0, 0, 0); } –

+0

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

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