차단 된 부스트 :: 스레드를 죽입니다
-
07-07-2019 - |
문제
나는 두 가지에서 입력에 대한 블록을 차단하는 응용 프로그램을 작성하고 있습니다. 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에 대해이 영역에서 다른 코드를 구현하는 것이 좋습니다.