Pergunta

Eu estou escrevendo um aplicativo que bloqueia na entrada de dois istreams.

Leitura a partir de qualquer istream é um (bloqueio) chamada síncrona, por isso, decidi criar dois Boost::threads para fazer a leitura.

Qualquer um destes segmentos podem chegar ao "fim" (com base em alguma entrada recebido), e uma vez que o "fim" é alcançado, tanto fluxos de entrada parar de receber. Infelizmente, eu não posso saber o que irá fazê-lo.

Assim, I pode não join() em ambas as linhas, porque apenas uma linha (não pode ser pré-determinado que uma) será realmente retornar (desbloquear).

I deve de alguma forma forçar o outro para sair, mas é bloqueada aguardando pela entrada, por isso em si não pode decidir que é hora de retorno (variáveis ??de condição ou o que não).

É a sua maneira de qualquer um:

  • Enviar um sinal de um boost :: segmento, ou
  • Força uma istream a "falha", ou
  • Mate um boost :: thread?

Nota:

  • Um dos istreams é cin
  • Eu estou tentando reiniciar o processo, então eu não posso fechar a entrada de fluxos de uma maneira que proíbe zerando-los.

Editar:

  • Eu sei quando o "fim" é atingido, e eu sei qual thread foi concluído com êxito, e que precisa ser morto. É o matando Eu preciso descobrir (ou uma estratégia diferente para a leitura de um istream).
  • Eu preciso ambos os tópicos a saída e limpeza corretamente: (

Obrigado!

Foi útil?

Solução

Eu não acho que há uma maneira de fazê-lo de plataforma cruzada, mas pthread_cancel deve ser o que você está procurando. Com um fio impulso que você pode obter o native_handle de um segmento, e pthread_cancel chamada nele.

Além disso, um caminho melhor seria usar o impulso asio equivalente a uma chamada de seleção em vários arquivos. Dessa forma, uma thread será bloqueado à espera para a entrada, mas poderia vir de qualquer fluxo de entrada. Eu não sei como é fácil fazer algo assim com iostreams embora.

Outras dicas

Sim, existe!

boost::thread::terminate() irá fazer o trabalho com suas especificações.

Ele fará com que o segmento alvo para lançar uma exceção. Assumindo que é não capturada, a pilha descontrair destruir corretamente todos os recursos e que encerra a execução de thread.

A rescisão não é instantânea. (O fio errado está sendo executado naquele momento, de qualquer maneira.)

Acontece em condições pré-definidas -. O mais conveniente para você provavelmente seria ao chamar boost::this_thread::sleep();, o que você poderia ter esse segmento fazer periodicamente

Se um fio de reforço é de bloqueio em um I / O de operação (por exemplo cin>>whatever), boost::thread::terminate() não irá matar o fio. cin i / o não é um ponto de terminação válido. Catch 22.

Bem no Linux, eu uso pthread_signal (SIGUSR1), uma vez que interrompe o bloqueio IO. Não há tal chamada em janelas como eu descobri quando portabilidade do meu código. Apenas um depreciado em chamada leitura socket. No windows você tem que definir explicitamente um evento que vai interromper seu bloqueio de chamadas. Portanto, não existe tal coisa (AFAIK) como uma forma genérica para interromper o bloqueio IO.

O projeto Boost.Thread lidar com isso por gerenciar pontos de interrupção bem identificados. Eu não sei boost.asio bem e parece que você não quer contar com ele de qualquer maneira. Se você não quiser refatorar para usar paradigma sem bloqueio, que você pode fazer é usar algo entre non-blocking (polling) e bloqueando IO. Isso é fazer algo como (código pseudo?):

while(!stopped && !interrupted)
{
    io.blockingCall(timeout);
    if(!stopped && !interrupted)
    {
        doSomething();
    }
}

Então você interromper seus dois tópicos e se juntar a eles ...

Talvez seja mais simples no seu caso? Se você tem uma linha mestre que sabe um segmento é encerrado você só tem que fechar a IO do outro segmento?

Edit: Pelo jeito que eu estou interessado na solução final que você tem ...

Eu tive um problema semelhante a mim mesmo e ter chegado a esta solução, que alguns outros leitores desta questão podem ser úteis:

Assumindo que você está usando uma variável de condição com um comando wait (), é importante para você saber que em Boost, a declaração wait () é um ponto de interrupção natural. Então, basta colocar um bloco try / catch em torno do código com a afirmação de espera e permitir que a função de encerrar normalmente em seu bloco catch.

Agora, supondo que você tenha um recipiente com seus ponteiros de rosca, iterar sobre seus ponteiros de rosca e de interrupção de chamada () em cada linha, seguido por join ().

Agora todos os seus tópicos irá encerrar graciosamente e qualquer limpeza de memória impulso relacionadas devem trabalhar de forma limpa.

Ao invés de tentar matar seu segmento, você sempre pode tryjoin o fio em vez disso, e se isso falhar, você juntar-se a outra vez. (Supondo que você sempre será capaz de juntar, pelo menos um de seus dois threads).

Em impulso: Linha você está procurando o timed_join função.

Se você quer olhar para a resposta correta, no entanto, que seria usar non-blocking io com esperas cronometrados. Permitindo-lhe obter a estrutura de fluxo de io síncrono, com o non-blocking de io assíncrona.

Você fala sobre a leitura de forma um istream, mas um istream é apenas uma interface. para stdin, você pode apenas fclose o descritor de arquivo stdin para interromper a leitura. Quanto aos outros, depende de uma onde você está lendo a partir de ...

Parece que threads não estão ajudando você a fazer o que você quer em uma maneira simples. Se Boost.Asio não está ao seu gosto, considere o uso select().

A idéia é fazer com que dois descritores de arquivos e usar select() para dizer-lhe que um deles tem entrada disponível. O descritor de arquivo para cin é tipicamente STDIN_FILENO; como obter o outro depende de suas especificidades (se for um arquivo, basta open()-lo em vez de usar ifstream).

Chamada select() em um loop para descobrir qual de entrada para ler, e quando você quiser parar, basta sair do loop.

No Windows, uso QueueUserAPC fazer fila um proc que lança uma exceção. Essa abordagem funciona bem para mim.

NO ENTANTO : Eu apenas encontrei esse impulso semáforos etc não são "alertable" na win32, então QueueUserAPC não pode interrompê-los.

Muito tarde, mas no Windows (e é precursores como VMS ou RSX para aqueles que rember essas coisas) eu usaria algo como ReadFileEx com uma rotina de conclusão que os sinais Quando terminar, e CancelIo se as necessidades de leitura de ser cancelada cedo .

Linux / BSD tem uma API subjacente totalmente diferente, que não é tão flexível. Usando pthread_kill para enviar um sinal funciona para mim, que vai parar a operação de leitura / aberto.

Vale a pena implementar código diferente nesta área para cada plataforma, IMHO.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top