문제

나는 두 가지에서 입력에 대한 블록을 차단하는 응용 프로그램을 작성하고 있습니다. istreams.

어느 쪽에서 읽는 것 istream 동기식 (차단) 호출이므로 두 개를 만들기로 결정했습니다. Boost::thread읽기를하기 위해.

이 스레드 중 하나가 "END"에 도달 할 수 있으며 (일부 입력 수신을 기준으로) "종료"에 도달하면 두 입력 스트림 모두 수신이 중지됩니다. 불행히도, 나는 어느 쪽이 그렇게할지 알 수 없습니다.

따라서 나는 할 수 없습니다 join() 두 스레드에서는 하나의 스레드 만 (어느 스레드를 미리 결정할 수 없음) 실제로 반환되지 않기 때문입니다 (차단 해제).

어떻게 든 다른 사람이 종료하도록 강요해야하지만 입력을 기다리는 것이 차단되므로 그 자체로 돌아올 시간을 결정할 수는 없습니다 (조건 변수 또는 그렇지 않은 것).

그들의 방법은 다음과 같습니다.

  • 신호를 부스트 :: 스레드를 보냅니다
  • 강제 istream "실패", 또는
  • 부스트 :: 실?

메모:

  • 중 하나 istreams ~이다 cin
  • 프로세스를 다시 시작하려고 노력하므로 입력 스트림을 재설정하는 방식으로 입력 스트림을 닫을 수 없습니다.

편집하다:

  • 나는 "끝"에 도달하는시기를 알고 있으며, 스레드가 성공적으로 완료되었으며 어떤 스레드가 죽어야하는지 알고 있습니다. 내가 알아 내야한다는 것은 (또는 istream에서 읽기위한 다른 전략)를 알아 내야합니다.
  • 종료하고 정리하려면 두 스레드가 모두 필요합니다 :(

감사!

도움이 되었습니까?

해결책

크로스 플랫폼을 수행 할 수있는 방법이 없다고 생각하지만 pthread_cancel은 당신이 찾고있는 것이되어야합니다. 부스트 스레드를 사용하면 얻을 수 있습니다 Native_handle 스레드에서, pthread_cancel을 호출하십시오.

또한 더 좋은 방법은 부스트를 사용하는 것입니다. ASIO 여러 파일에서 선택한 호출에 해당합니다. 이렇게하면 하나의 스레드가 입력 대기 대기 중이지만 입력 스트림 중 하나에서 발생할 수 있습니다. 그래도 ioStreams와 함께 이런 일을하는 것이 얼마나 쉬운 지 모르겠습니다.

다른 팁

네가 있습니다!

boost::thread::terminate() 사양에 따라 작업을 수행합니다.

대상 스레드가 예외를 던지게됩니다. 그것이 잡히지 않았다고 가정하면 스택은 모든 자원을 제대로 파괴하고 스레드 실행을 종료합니다.

종료는 즉각적이지 않습니다. (어쨌든 잘못된 실이 실행 중입니다.)

사전 정의 된 조건에서 발생합니다. boost::this_thread::sleep();, 그 스레드가 정기적으로 수행 할 수 있습니다.

부스트 스레드가 I/O 작업에서 차단되는 경우 (예 : cin>>whatever), boost::thread::terminate() 실을 죽이지 않을 것입니다. cin I/O는 유효한 종료 지점이 아닙니다. 캐치 22.

Linux에서는 io 차단을 방해하기 때문에 pthread_signal (sigusr1)을 사용합니다. 코드를 포팅 할 때 발견 한 Windows에 그러한 전화가 없습니다. 소켓 읽기 호출에서 더 이상 사용되지 않는 것. Windows에서는 차단 통화를 방해하는 이벤트를 명시 적으로 정의해야합니다. 따라서 IO 차단 차단을 방해하는 일반적인 방법과 같은 것 (AFAIK)은 없습니다.

Boost.thread 디자인은 잘 식별 된 인터럽트 포인트를 관리하여이를 처리합니다. 나는 boost.asio를 잘 모르고 당신은 어쨌든 그것에 의존하고 싶지 않은 것 같습니다. 비 블로킹 패러다임을 사용하도록 리팩토링을 원하지 않는 경우, 할 수있는 일은 비 블로킹 (폴링)과 IO 차단 사이에 무언가를 사용하는 것입니다. 그것은 (의사 코드?)와 같은 것입니다.

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

그런 다음 두 스레드를 방해하고 가입합니다 ...

아마도 당신의 경우 더 간단합니까? 하나의 스레드를 알고있는 마스터 스레드가있는 경우 다른 스레드의 IO를 닫아야합니까?

편집 : 그건 그렇고 나는 당신이 가진 최종 솔루션에 관심이 있습니다 ...

나는 비슷한 문제가 있었고이 솔루션에 도달했는데,이 질문의 다른 독자들은 유용 할 수 있습니다.

대기 () 명령으로 조건 변수를 사용하고 있다고 가정하면 Boost에서 Wait () 문은 자연스러운 인터럽트 지점임을 아는 것이 중요합니다. 따라서 대기 명령문으로 코드 주위에 시도/캐치 블록을 넣고 기능이 캐치 블록에서 정상적으로 종료되도록합니다.

이제 당신이 당신의 스레드 포인터가있는 컨테이너가 있다고 가정하고, 스레드 포인터를 반복하고 각 스레드에서 interprupt ()를 호출 한 다음 join ()을 호출하십시오.

이제 모든 스레드가 우아하게 끝나고 부스트 관련 메모리 정리가 깨끗하게 작동해야합니다.

스레드를 죽이려고하는 대신 대신 스레드를 대신 시도 할 수 있으며 실패하면 대신 다른 사람을 결합시킬 수 있습니다. (항상 두 스레드 중 하나 이상을 결합 할 수 있다고 가정합니다).

부스트 : 스레드를 찾고 있습니다 timed_join 기능.

그러나 정답을보고 싶다면 시간이 지남에 따라 비 차단 IO를 사용하는 것입니다. 비동기 IO의 비 차단과 함께 동기 IO의 흐름 구조를 얻을 수 있습니다.

당신은 istream 형식을 읽는 것에 대해 이야기하지만, istream은 단지 인터페이스 일뿐입니다. Stdin의 경우 Stdin 파일 디스크립터를 FCLOSE로 읽을 수 있습니다. 다른쪽에 관해서는, 그것은 당신이 읽고있는 곳에 달려 있습니다 ...

스레드는 간단한 방식으로 원하는 작업을 수행하는 데 도움이되지 않는 것 같습니다. boost.asio가 당신이 좋아하지 않는 경우, 사용을 고려하십시오. select().

아이디어는 두 개의 파일 설명자를 얻고 사용하는 것입니다. select() 그들 중 어느 것이 입력을 사용할 수 있는지 알려줍니다. 파일 디스크립터 cin 일반적으로 STDIN_FILENO; 다른 하나를 얻는 방법은 세부 사항에 따라 다릅니다 (파일 인 경우 open() 사용하는 대신 ifstream).

부르다 select() 루프에서 읽을 입력을 찾아서 멈추고 싶을 때 루프에서 벗어나십시오.

Windows에서 QueueuserApc를 사용하여 예외를 던지는 Proc를 대기합니다. 그 접근법은 나에게 잘 작동합니다.

하지만: 방금 Boost Mutxes 등이 Win32에서 "경고 가능"하지 않으므로 QueueUuserAPC를 방해 할 수 없습니다.

매우 늦었지만 Windows에서 (그리고 그런 것들을 깔개하는 사람들의 VMS 또는 RSX와 같은 선구자) 완료시 신호를 완성한 완료 루틴과 함께 ReadFileEx와 같은 것을 사용하고 읽기를 일찍 취소 해야하는 경우 Cancelio를 사용했습니다.

Linux/BSD는 완전히 다른 기본 API를 가지고 있으며 유연하지 않습니다. PTHREAD_KILL을 사용하여 신호를 보내면 읽기/오픈 작업이 중지됩니다.

각 플랫폼 인 IMHO에 대해이 영역에서 다른 코드를 구현하는 것이 좋습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top