2013-03-26 3 views
0

서버에 연결하는 클라이언트 응용 프로그램을 만들고 다른 기능과 함께 서버 채팅을 파일에 기록하므로 나중에 규칙 위반이 처벌 될 수 있습니다.
불행히도 응용 프로그램에 적어도 두 개의 스레드가 있어야합니다. 수신자 루프와 송신기 루프 타이밍 사전 처리가 서버에 필요합니다. 즉, 파일에 데이터를 로깅 할 때 스레드 안전 솔루션이 필요합니다.
이 스레드가 같은 시간 (가능한 한)에서 로그 정보를 보내는 경우 발생할 수 있습니다 것입니다 :멀티 스레드 파일 스트림

logfile.txt: 
chat: Hello my name is Duke 
chat: Hell[WARNING]: Hacker detectedo my name is John 

당신은 다른 주입 한 문장을 볼 수 있습니다. 나는 이런 일이 일어나기를 원하지 않는다. 내 std::cout 출력도 동일하지만 그렇게 중요하지는 않습니다.

질문 :

  1. 어떻게 한 번에 하나 개의 데이터를 기록 할 수 std::ofstream을해야합니까? (다른 것을 기억하고 중간에 삽입하지 않고 나중에 삽입)
  2. 파일이 다른 스레드에 의해 닫혔는지 어떻게 확인합니까? (또는 오류)

보너스 질문 : 당신이 std::cout 위해 같은 문제를 해결할 수 있을까요?

+4

파일에 쓰기 전에 뮤텍스를 잠그고 싶을 때 (또는'std :: cout') –

+0

그냥 다른 입력을 차단하고 싶지는 않지만'std'를 다음과 같이 순서대로 만듭니다. 쓰기. 먼저 한 입력을 취한 다음 다른 입력을 취하십시오. –

+0

황태자의 마지막 단락으로 막을 수 있습니다. –

답변

4

표준 스트림에는 스레드 안전성 보장이 없습니다. 수행하려는 작업을 안전하게 수행하는 유일한 방법은 스트림에 대한 액세스를 직렬화하는 것입니다.

가장 쉬운 해결책은 뮤텍스에서 스트림과 관련된 모든 문장을 래핑하는 것입니다.

{ 
    std::lock_guard<std::mutex> locked(gCoutMutex); 
    std::cout << "This is a message" << std::endl; 
} 

로거의 경우 특히 올바른 방법은 메시지 큐가있는 로깅 스레드를 만드는 것입니다. 다른 스레드가 기록하려고 할 때, 단지 대기열에 메시지를 게시하고, 기록 스레드는 대기열을 통해 모든 것을 디스크에 기록합니다.

+0

채팅 메시지에 대한 대기열과 비슷한 스레드가 서버에 전송되었지만 'std :: vector'도 안전하지 않으므로 때때로 응용 프로그램이 충돌합니다. –

+0

+1 ... 물론, 큐에 접근 할 때 더 정확한 * 접근법에서 뮤텍스가 여전히 필요합니다. –

+0

표준 라이브러리는 당신을 도울 방법이 없습니다. 자신 만의 스레드 안전 큐를 작성하거나 다른 라이브러리에서 하나를 사용해야합니다. 예를 들어,'boost :: asio :: io_service' 또는 Boost.LockFree에있는 컨테이너 중 하나. 내가 선호하는 접근 방식은'io_service'이다. –