2008-11-07 8 views
20

나는 두 개의 입력에서 차단하는 응용 프로그램을 작성 중입니다. istreams.차단 된 부스트 :: 스레드

istream 중 하나를 읽는 것은 동기식 (차단) 호출이므로이 두 가지를 작성하여 읽기를 수행하기로했습니다.

이러한 스레드 중 하나는 수신 된 일부 입력에 따라 "종료"에 도달 할 수 있으며 "종료"에 도달하면 두 입력 스트림 모두 수신을 중지합니다. 불행히도, 나는 그렇게 할 것인지 알 수 없다.

따라서 하나의 스레드 만 (어느 블록을 미리 지정할 수는 없지만) 실제로 반환 (차단 해제) 할 수 있기 때문에 두 스레드에서 join()을 사용할 수 없습니다.

나는 다른 것을 강제로 종료해야하지만 입력을 기다리는 동안 차단되므로 스스로 반환 할 시간을 결정할 수 없습니다 (조건 변수 또는 그렇지 않은 경우).

하는 중 수있는 방법들이 있습니다 :

  • 가 부스트 : : 스레드, 또는
  • istream이 "실패"에 힘을 신호를 보내기, 또는
  • 는 부스트 : 스레드를 죽여?

참고 : istreams

  • 하나는 내가 프로세스를 다시 시작하려고 cin
  • , 그래서이 입력을 설정하라는 금지하는 방식으로 스트림을 닫을 수 없습니다.

편집 : 사망 할 필요가

  • 은 "끝"에 도달하면 내가 알고, 내가 성공적으로 완료하는 스레드 알고합니다. 내가 알아야 할 살인 (또는 istream에서 읽기위한 다른 전략).
  • 나는 종료하고 제대로 정리 :(양쪽 스레드를 필요

감사합니다! 내가 크로스 플랫폼을 할 수있는 방법이 있다고 생각하지 않지만, pthread_cancel 당신이 찾고있는 무엇을해야

답변

4

부스트 스레드를 사용하면 스레드에서 native_handle을 가져올 수 있으며 pthread_cancel을 호출 할 수 있습니다.

더 좋은 방법은 복수 파일의 선택 호출에 해당하는 부스트 asio을 사용하는 것입니다. 입력을 기다리는 것을 막을 수는 있지만 입력 str에서 올 수 있습니다. eam. 나는 iostream으로 이런 일을하는 것이 얼마나 쉬운 지 모르겠습니다.

+0

운 좋게도 지금 리눅스 머신 용으로 개발하고 있지만 휴대용 버전을 선호합니다. 고마워! – mmocny

+0

비슷한 상황에서 pthread_cancel()이 취소 기능을 사용하지 않고 취소 유형을 ASYNCHRONOUS로 설정하지 않았습니다. – gatopeich

0

스레드를 죽이려고하는 대신 스레드 대신 시도해 볼 수 있으며, 실패하면 대신 다른 스레드에 참여할 수 있습니다. (당신은 항상 두 스레드 중 적어도 하나에 합류 할 수 있다고 가정합니다).

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

그러나 정답을보고 싶다면 시간 초과 대기와 함께 비 차단 io를 사용하는 것이 좋습니다. 비동기식 io의 비 차단 기능을 사용하여 동기식 io의 흐름 구조를 얻을 수 있습니다.

istream 형식을 읽는 것에 대해 이야기하지만, istream은 인터페이스 일뿐입니다. stdin의 경우 stdin 파일 설명자를 fclose하여 읽기를 인터럽트 할 수 있습니다. 다른 것에 관해서는, 당신이 어디에서 읽고 있는지에 달려 있습니다 ...

+0

이 작업을 수행하는 방법에 대한 제안이 있으십니까? 나는 cin과 함께 불가능한 (이식 할 수있는) 느낌이었다. 그리고 저는 이미 하나의 스레드에 제대로 합류하고 있다고 말했고, 다른 하나는 처리해야합니다. 그래도 고마워. – mmocny

+0

다시 한번 감사드립니다. 하지만 당신이 그 질문을 오해하고 있다고 생각합니다. 스레드 중 하나가 절대 참여하지 않습니다(). 나는 쓰레드 중 하나를 조인하는 방법과 그렇지 않은 것을 식별하는 방법을 안다. 내가 필요로하는 것은 다른 스레드가 차단 해제되도록하는 것입니다. (또는 다른 해결책을 제시하십시오) – mmocny

0

Windows에서는 QueueUserAPC를 사용하여 예외를 던진 proc을 대기열에 넣습니다. 그 접근 방식은 나를 위해 잘 작동합니다.

HOWEVER : 나는 boostmutexes 등이 win32에서 "경고 가능"하지 않으므로 QueueUserAPC가 이들을 인터럽트 할 수 없다는 것을 발견했습니다.

1

리눅스에서는 IO를 차단하는 데 방해가되므로 pthread_signal (SIGUSR1)을 사용합니다. 내 코드를 이식 할 때 발견 한 창에 대한 호출이 없습니다. 소켓 읽기 호출에서 더 이상 사용되지 않는 호출입니다. 창에서 차단 호출을 중단시킬 이벤트를 명시 적으로 정의해야합니다. 그래서 IO (IO) 차단을 방해하는 일반적인 방법으로 그러한 일 (AFAIK)이 없습니다.

boost.thread 디자인은 잘 식별 된 인터럽트 지점을 관리하여이를 처리합니다. 나는 부스트를 잘 모른다. 아시오. 어쨌든 당신이 그것에 의지하기를 원하지 않는다. 비 차단 패러다임을 사용하도록 리팩토링하지 않으려면 비 차단 (폴링)과 차단 IO 사이에 무언가를 사용하면됩니다. (? 의사 코드) : 다음

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

당신이 당신의 두 개의 스레드를 중단하고 그들과 합류 ...

은 아마도 그것은 귀하의 경우 간단하다 그 같은 일을 할 것입니다? 하나의 쓰레드가 종료되었다는 것을 알고있는 마스터 쓰레드를 가지고 있다면 다른 쓰레드의 IO를 닫아야한다.

편집 : 당신이 최종 솔루션에 관심이 있어요 그런데 은 ...

0

스레드가 당신이 간단한 방법으로 원하는 것을 할 도움이되지 않습니다 보인다. Boost.Asio가 마음에 들지 않으면 select()을 사용해보십시오.

아이디어는 두 개의 파일 설명자를 가져와 select()을 사용하여 사용 가능한 입력을 알리는 것입니다. cin의 파일 설명자는 일반적으로 STDIN_FILENO입니다. 다른 하나를 얻는 방법은 귀하의 세부 사항에 달려 있습니다 (파일 인 경우 ifstream 대신 open()).

루프에서 select()을 호출하여 읽을 입력을 찾고 중지하려는 경우 루프에서 벗어납니다.

4

예!

boost::thread::terminate() 귀하의 사양에 맞게 작업을 수행 할 것입니다.

이렇게하면 대상 스레드가 예외를 throw합니다. 잡히지 않는다고 가정하면 스택은 모든 리소스를 적절히 제거하고 스레드 실행을 종료합니다.

종료가 순식간에 이루어지지 않습니다. (잘못된 스레드가 그 순간에 실행 중입니다.)

이것은 미리 정의 된 조건에서 발생합니다. boost::this_thread::sleep();을 호출 할 때 가장 편리 할 것입니다.이 스레드는 주기적으로 해당 스레드를 가질 수 있습니다.

+0

무슨 말씀 이세요? __boost__에는 boost :: thread :: terminate()와 같은 함수가 없습니다. –

+1

안녕하세요, @ YagamyLight. 정말 답을 원한다면 잘 모르겠지만,이 답변을 작성한 후에'boost :: thread :: terminate'에 어떤 일이 일어 났는지에 대한 질문을 자유롭게 게시 할 수 있습니다. –

4

부스트 스레드가 I/O 작업 (예 : cin>>whatever)에서 차단되는 경우 boost::thread::terminate()은 스레드를 죽이지 않습니다. cin I/O가 유효한 종단점이 아닙니다.

1

캐치 22. 나 자신을 비슷한 문제를 가지고 있었고,이 질문의 일부 다른 독자 유용하게 찾을 수있는이 솔루션에 도달했습니다 :

, 당신은 대기() 명령을 사용하여 조건 변수를 사용하고 있는지를 가정을 Boost에서 wait() 문은 자연스러운 인터럽트 지점이라는 것을 아는 것이 중요합니다. 따라서 try/catch 블록을 wait 문으로 코드 주위에 놓고 함수가 catch 블록에서 정상적으로 종료되도록 허용하십시오.

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

이제 모든 스레드가 정상적으로 종료되고 모든 부스트 관련 메모리 정리가 정상적으로 작동합니다.

0

매우 늦었지만 Windows에서 (그리고 그러한 것들을 기억하는 사람들에게는 VMS 나 RSX와 같은 선구자입니다.) 나는 완료되면 신호를 보내는 완료 루틴과 ReadFileEx와 같은 것을 사용하고, 읽어야 할 경우에는 CancelIO를 취소해야합니다 이른.

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

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