Search

'C++'에 해당되는 글 1건

  1. 2012.02.17 boost, io_service 그리고 io_service.run() (3)

boost, io_service 그리고 io_service.run()

프로그래밍 2012.02.17 22:09 Posted by 아일레프

boost, 엄청 훌륭하다. 정말 좋다. C++의 놀라움은 C#의 Linq와 같은 기능을 추가적인 프로그램 언어 문법이 없어도 (lambda와 같은) meta programing 으로 구현할 수 있다는 사실에 있다. 물론 Template 코드인 특정 함수가 Parameter로 어떤 Type을 원하는지 알기란 나같은 초짜로서는 너무 버겁다. 하지만 이때 탓해야 할 것은 부족한 나. boost그리고 그것이 가능하게 하는 c++언어는 눈물 나도록 아름답고 내가 완전히 그것을 정복하기란 불가능해 보일 정도로 높은 위치에 있다. 엉엉엉

여기까진 순전히 사족이고, 본론을 시작한다. 요즘 TCP/IP Socket 프로그래밍 할 일이 계속 생겨서 이 boost를 계속 활용하고 있는데, 정말 어이 없는 실수로 4시간을 소비했다. 이것이 실수인지 판단하기 위해 얼마나 많은 시간을 허비했는지. 엉엉엉.

io_service는 Thread Pool과 비슷한 역할을 한다. boost::asio::ip::tcp::socket은 이런 io_service의 성질을 이용해 async_write, async_read를 구현할 수 있다. 자, 그럼 내가 고생했던 사항을 여기 간단하게 고쳐 적어본다.

boost::asio::io_service io_service;
TcpIpClientManager manager(io_service);
boost::thread thread(boost::bind(&boost::asio::io_service::run, &io_service));
io_service.post(boost::bind(&MainStarter::PostProcessUsingIoService, this));

자, 위 코드의 의도는 알 것이다. TcpIpClientManager라는 객체는 TCP/IP통신을 위해 만든 객체이다. 내부에 private boost:asio::ip::tcp::socket을 가지고 있다.

io_service.run()을 호출하면 주 thread가 Block되므로 thread로 돌렸다. 그리고 PostProcessUsingIoService라는 함수를 io_service에 맡겨 실행되게 했다.

자, 어떤 일이 벌어질까? 이 코드의 문제점은 무엇일까? 이 경우 PostProcessUsingIoService 함수는 실행 될 수도 있고, 실행되지 않을 수도 있다. 무슨 말인고 하니, TcpIpClientManager 내부에서 io_service를 사용해 어떤 활동을 하는 코드가 실행 중이라면 저 코드는 실행된다. 그런데 만약 io_service를 사용하는 모든 일들이 종료 되었다면 저 코드는 실행되지 않는다. io_service가 run 상태가 아니기 때문이다.

이것은 io_service문서를 조금만 주의 깊게 보면 알 수 있다.

Some applications may need to prevent an io_service object's run() call from returning when there is no more work to do. For example, the io_service may be being run in a background thread that is launched prior to the application's asynchronous operations. The run() call may be kept running by creating an object of type io_service::work:

젠장. 왜 document를 보지 않고 예제만 보고 프로그래밍을 했기에 이와 같은 멍청한 일이 생겼다. 나를 탓할 수 밖에 없다. 그래서, PostProcessUsingIoService가 t실행 되는 것을 항상 보장 하려면 - 즉 io_service가 항상 run상태이게 하려면 - 다음과 같이 work를 사용해야 한다.

boost::asio::io_service io_service;
boost::asio::io_service::work work(io_service);
TcpIpClientManager manager(io_service);
boost::thread thread(boost::bind(&boost::asio::io_service::run, &io_service));
io_service.post(boost::bind(&MainStarter::PostProcessUsingIoService, this));

결론.

Document는 졸라 중요합니다. 당신의 소중한 시간을 낭비하지 않기 위한 최선의 방법은 당장 구현된 예제를 보는 것이 아니라 Document를 보는 것입니다.

신고


 

티스토리 툴바