검색결과 리스트
Programming/Boost asio에 해당되는 글 9건
- 2015.04.11 Tutorial 5. Synchronising handlers in multithreaded programs
- 2015.03.17 Tutorial 4. member function handler
- 2015.03.15 Tutorial 3. Binding arguments to a handler
글
Tutorial 5. Synchronising handlers in multithreaded programs
다음 내용에 기반함
http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/tutorial/tuttimer5.html
이번 튜토리얼 에서는 boost::asio::strand 클래스를 사용하여 멀티스레드 프로그램에서 콜백 핸들러를 동기화하는 방법을 알아보자.
이전 4개의 튜토리얼에서는 io_service::run() 함수를 오로지 하나의 스레드에서만 호출하였기 때문에 핸들러 동기화 이슈를 피할수 있었다. ( asio 라이브러리는 콜백 핸들러들이 io_service::run() 을 호출한 스레드에서만 실행될 수 있도록 보장해준다. 거기에, io_service::run() 을 하나의 스레드에서만 부름으로써, 동시에 실행되지 않는 것을 보장받은 것이다.)
스레드를 하나만 이용하여 접근하는 것은 asio 를 이용한 어플리케이션을 시작하기에 좋았지만, 서버와 같은 프로그램에서 다음과 같은 제한이 존재한다는 것이다.
* 핸들러가 많은 시간을 소요할 경우 응답성이 떨어진다.
* 멀티 프로세서 시스템에서 확장성이 없다.
이 문제를 해결하기 위해, io_service::run() 을 스레드 풀에서 호출하는 것으로 차선책을 찾아볼 수 있다.
그러나, 이렇게 되어 핸들러가 동시에 실행되는 것이 가능하게 되어, 스레드 safe 하지 않은 공용되는 데이터에 접근하는 핸들러들을 동기화하는 방법이 필요하게 된다.
이전 튜토리얼과 마찬가지로 Printer 를 정의하는 것에서부터 시작해보자. 타이머를 동시에 두개 돌리는 것으로 확장해볼 것이다.
class printer { public:
여기에 boost::asio::deadline_timer 멤버 쌍을 초기화 하는 코드와 boost::asio::strand 타입인 stand_ 멤버를 초기화하는 코드를 추가한다. strand 를 통해 디스패치 되는 핸들러들이 다음에 호출 되는 핸들러가 시작되기 전에 끝나는 것을 보장한다.
이건 몇개의 스레드가 io_service::run() 을 호출 했냐와는 관계가 없다. 물론, 핸들러들은 동시 다발적으로 다른 핸들러들에서 실행 되어 boost::asio::strand 로 인해 디스패치 되지 않을 것이며, 다른 boost::asio::strand 객체를 통해 디스패치 되지 않을 것이다.
printer(boost::asio::io_service& io) : strand_(io), timer1_(io, boost::posix_time::seconds(1)), timer2_(io, boost::posix_time::seconds(1)), count_(0) {
비동기 동작들을 초기화 할때, 각각의 콜백들은 boost::asio::strand 객체를 통해 "wrapped" 된다. strand::wrap() 함수는 핸들러를 포함한 객체를 boost::asio::strand 객체를 통해 새롭게 반환한다. 핸들러를 동일한 boost::asio::strand 를 통해 'wrapping' 함으로써, 동시에 실행되지 않음을 보장할 수 있다.
timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this))); timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this))); } ~printer() { std::cout << "Final count is " << count_ << "\n"; }
멀티스레드 프로그램에서, 비동기 동작들은 공유 리소스에 접근할때는 동기화가 이루어 져야한다. 이 튜토리얼에서는, 핸들러 (print1 과 print2 ) 에서 공유되는 리소스가 std::cout 과 count_ 라고 하자.
void print1() { if (count_ < 10) { std::cout << "Timer 1: " << count_ << "\n"; ++count_; timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1)); timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this))); } } void print2() { if (count_ < 10) { std::cout << "Timer 2: " << count_ << "\n"; ++count_; timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1)); timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this))); } } private: boost::asio::io_service::strand strand_; boost::asio::deadline_timer timer1_; boost::asio::deadline_timer timer2_; int count_; };
메인 함수에서는 이제 io_service::run() 이 두개의 스레드에서 호출되게 된다 : 하나는 메인스레드, 하나는 추가된 스레드에서 - 이것은 boost::thread 객체를 통해 이루어진다.
싱글스레드에서 그랬던 것처럼 io_service::run() 에 대한 동시적 호출은 work 가 가 남아 있는 동안 실행되게 된다. 백그라운드의 스레드는 비동기 작업이 완료되기 전까지 완료되지 않는다.
int main() { boost::asio::io_service io; printer p(io); boost::thread t(boost::bind(&boost::asio::io_service::run, &io)); io.run(); t.join(); return 0; }
full-source code
실행 결과
'Programming > Boost asio' 카테고리의 다른 글
Daytime.2 - A synchronous TCP daytime server (0) | 2015.04.19 |
---|---|
Daytime.1 - A synchronous TCP daytime client (0) | 2015.04.13 |
Tutorial 4. member function handler (0) | 2015.03.17 |
Tutorial 3. Binding arguments to a handler (0) | 2015.03.15 |
Tutorial 2. async_timer (0) | 2015.03.14 |
설정
트랙백
댓글
글
Tutorial 4. member function handler
다음에 기반함
http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/tutorial/tuttimer4.html
이전 튜토리얼과 달라진 점은 클래스로 교체하면서 timer 와 count 를 멤버변수로 변경하고, 이에 따라 불필요해진 timer 와 count 함수인자를 제거했다.
(이 튜토리얼 과정을 정확히 인지하지 않은채로 포스팅하다보니 이번 포스팅에서 배우는 내용인 멤버함수의 bind 호출과 같은 내용이 이미 소개가 되어 큰 의미가 없는 튜토리얼이 됐다.
그냥 흘깃 넘어가자.)
MemberHandler
결과
'Programming > Boost asio' 카테고리의 다른 글
Daytime.1 - A synchronous TCP daytime client (0) | 2015.04.13 |
---|---|
Tutorial 5. Synchronising handlers in multithreaded programs (0) | 2015.04.11 |
Tutorial 3. Binding arguments to a handler (0) | 2015.03.15 |
Tutorial 2. async_timer (0) | 2015.03.14 |
Tutorial 1. sync_timer (0) | 2015.02.04 |
설정
트랙백
댓글
글
Tutorial 3. Binding arguments to a handler
다음에 기반함
http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/tutorial/tuttimer3.html
이제 AsyncTimer 를 수정해서 1초에 한번씩 실행 되도록 수정하겠다고 한다.
타이머 시간을 수정하고 (기존 5초), 다시 내부에서 새로운 비동기 wait 을 호출하면 된다.
즉, 핸들러내부에서 타이머 객체에 접근하는 것이 필요하다.
2 개의 인자를 추가한다.
boost::asio::deadline_timer* t (deadline timer 는 reference 가 불가능하게 되어있다.) 와 int* count 이다. (최종 count 값을 리턴받으려면 pointer 로. )
count 는 6번째로 타이머가 실행되었을 때는 타이머를 다시 실행시키지 않도록 하기 위해 추가한 인자다.
io_service 에는 stop 과 같은 명시적으로 중지를 요청하는 호출이 없고, 대신 'work' 가 없을때 함수가 종료된다는 것을 상기하자.
카운트가 5에 도달하면 새로운 async_wait 을 호출하지 않는 것으로 io_service 는 work 가 소진되고 동작이 중지 될 것이다.
그리고 타이머의 만료시간을 이전 만료시간으로부터 1초 뒤로 지정한다. 이전 시간에서 계산하는 것으로 핸들러를 처리하는데 소요된 시간으로 인해 지연되지 않도록 한다.
periodTimer
메인함수. 호출부
'Programming > Boost asio' 카테고리의 다른 글
Tutorial 5. Synchronising handlers in multithreaded programs (0) | 2015.04.11 |
---|---|
Tutorial 4. member function handler (0) | 2015.03.17 |
Tutorial 2. async_timer (0) | 2015.03.14 |
Tutorial 1. sync_timer (0) | 2015.02.04 |
0. 소개 (0) | 2015.02.02 |