리눅스 GNU C++에서 타이머 컴포넌트를 만들기
[목차(도우미)]
리눅스(Linux)에서 단순히 GNU C++(흔히 gcc, GNU Compiler Collection 라고 부르는 C++)에서
인용되는 시스템 함수(System call)를 호출하여 타이머(Timer)를 사용하는 것도 좋은 방법이다.
타이머 컴포넌트
한번 만든 소스코드를 재활용하기 위한 객체 지향 기법(Object-oriented design)을 좋아하는 사람이라면 타이머 컴포넌트(Component)를 만들어 두고 싶어진다.GNU C++에서 사용되는 함수는 signal(SIGVTALRM, handler)를 적용해서 이벤트 핸들러(Event handler)를 등록해 두면 되는데 handler 함수를 클래스의 멤버 함수로 선언하면 나중에 계승(inherit)처리를 하려고 설계한다면 제대로 컴파일이 통하지 않는다.
기본 샘플 : 소스를 복사해서 사용하는 방식
복사해서 개발하는 경우에 자주 보는 샘플 소스.방식 자체가 나쁜 것은 아니지만 재활용하려면 여전히 소스코드를 복사해서 처음부터 써나가야 한다.
- void handler(int signo){ printf("handler called-----"); }
- int main(){
- // ...
- // this is OK typical sample source
- signal(SIGALRM, handler);
- struct itimerval delay;
- delay.it_value.tv_sec = 5;
- // ...
- int ret = setitimer(ITIMER_REAL, &delay, NULL);
- // ...
- }
클래스를 선언한 방식 : 컴파일 에러
안타깝게도 컴파일 조차 안된다.정적 메소드(static) 로 선언해 주어야 된다는 에러가 발생한다. 따라서 해결 방법은 함수 포인터를 사용하여 호출처에서 직접 함수를 넘겨 주는 것이다. 예를 들어 생성자에서 함수 포인터를 넘겨 주는 것이 가능하다.
- class Timer {
- public:
- Timer();
- ~Timer();
- void TickEvent(int signo){printf("called...")};
- // ...
- };
- Timer::Timer(){
- // ...
- // this is compile NG
- signal(SIGALRM, TickEvent);
- struct itimerval delay;
- delay.it_value.tv_sec = 5;
- // ...
- int ret = setitimer(ITIMER_REAL, &delay, NULL);
- // ...
- }
클래스 생성시에 함수 포인터를 넘겨주는 방식
클래스의 인스턴스 생성시에 미리 준비한 이벤트 핸들러를 인수로 넘겨 주어야 한다.생성시에 핸들러를 넘겨주어야 한다는 점에서 사용시 제약이 있다. 독특한 사용법이라고나 할까.
- class Timer {
- public:
- Timer(void (*TickHandler)(int));
- ~Timer();
- // ...
- };
- Timer::Timer(void (*TickHandler)(int)){
- // ...
- // this is nice to compile but...
- signal(SIGALRM, TickHandler);
- struct itimerval delay;
- delay.it_value.tv_sec = 5;
- // ...
- int ret = setitimer(ITIMER_REAL, &delay, NULL);
- // ...
- }
클래스의 이벤트를 선언한 방식
이벤트를 정의하는 방법이 C++에서는 파스칼(Delphi, Pascal)에서 처럼 깔끔하게 보이지 않지만, 이번 경우는 이벤트로 정의하는 것이 낫다.- class Timer {
- public:
- Timer();
- ~Timer();
- // event
property declaration
- void (*TickEvent)(int);
- // ...
- };
- Timer::Timer(){
- // ...
- // this calles event procedure when signal occurs
- signal(SIGALRM, TickEvent);
- struct itimerval delay;
- delay.it_value.tv_sec = 5;
- // ...
- int ret = setitimer(ITIMER_REAL, &delay, NULL);
- // ...
- }
함수 포인터로 구현한다는 것 자체가 델파이식으로 말한다면 이벤트 속성(Event Property)를 구현하는 것이다. 계승에 의한 처리 구현과 함수 포인터에 의한 처리 구현의 방식의 차이는 있지만 본질적으로 처리를 클래스에서 따로 분리하는 것은 같다고 할 수 있다.
GNU C 에서 구현하는 예제
(단지 손으로 책에 나온 내용을 다시 입력하기가 번거로와서 기존 공개 페이지를 연결해 둔다.)
http://www.codeguru.com/forum/showthread.php?t=356101
'연구개발 이야기' 카테고리의 다른 글
인스톨러(*.msi) 에 환경변수 경로를 추가하는 방법 (0) | 2011.06.11 |
---|---|
소스코드리뷰(XXXII) 한번의 루프로 최대한 처리하라 (0) | 2011.05.21 |
리눅스 GNU C++에서 타이머 컴포넌트를 만들기 (4) | 2011.04.13 |
[메모] php에서 https로의 소켓 접속을 하려면 (0) | 2011.03.23 |
소스코드리뷰(XXXI) 재사용을 염두에 두라 (0) | 2011.03.02 |
언제부턴가 '재사용'을 염두해 하나둘씩 만들기 시작했는데, 정리가 안되어 잘 쓰지도 않네요 ㅠ.ㅠ 좋은 하루 되시고^^
지금부터 약간 본문을 수정할 생각인데, 댓글을 달아 주셨군요. 이벤트로 구현하는 부분에 보완할 참입니다. 기대해 주세요.
안녕하세요?
이벤트로 구현하는 부분을 보완해두었습니다.
오랜만에 다시 읽어보니 감회가 새롭다. 나도 리눅스에서 여러가지 연구했었구나.