2008년 11월 27일 목요일

CallBack Function (콜백 함수)

■ CallBack Function (콜백 함수)




1. 존재의 목적   - 프로그램이 실행되는 동안 지속적으로 수행해야 할 작업이 있을 때.
   - callback 함수를 호출한 쪽의 데이터를 callback 함수가 위치한 곳에서 사용해야 할 때.
  

2. 의미   - 운영체제가 API함수를 제공하는 것과 달리, 응용프로그램이 callback 함수를 제공한다.
   - 특정 조권을 만족 하였을 때 운영체제가 호출한다.
   - callback 함수는 오직 운영체제가 호출하며, 응용프로그램이 직접 callback 함수를 호출하지 못한다.
   - callback 함수마다 정해진 함수 원형이 있다.

   ※ 조권이 있을 때 윈도우 메시지를 호출 하기 보다 callback 함수를 호출 하는 이유?
      -  윈도우 메시지는(WM_TIMER. 등등) 메시지 마다 우선순위가 있어서 실행 순서에 밀려 늦게 호출 될수 있음.
      -  callback 함수는 조권이 발생 하였을 때 바로 실행됨.


3. 대표적인 callback 함수    운영체제가 callback 함수를 호출 할 수 있도록 callback 함수를 등록 해주는 함수가 존재한다.
   즉, 응용프로그램은 callback 함수를 윈도우 시스템에 알린다.
   
    - ::SetTimer(hWnd, 2, 5000, NULL);
                VOID CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
                조권 : 지정해준 시간마다 callback 함수 호출

    - ::EnumWindows(WINDENUMPROC lpEnumFunc, LPARAM lParam);
                 BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam);
                 조권 : 최상위 모든 윈도우 검색, 그 핸들을 callback 함수로 전달
                          모든 윈도우를 다 찾거나, callback 함수가 FALSE를 리턴할때까지 호출됨.

    - ::윈도우 등록 및 생성
                 LRESULT CALLBACK WndProc(...)
                 조권 : 메인윈도우가 메시지를 받았을 때


4. callback 함수와 Thread 의 이해
   - callback 함수를 호출할 조권을 만족하는지 지속적으로 검사하는 과정이 필요하다.
     이러한 경우 보통 별도의 Thread 를 이용한다.
   - 즉, Main Thread 와 자식 Thread 는 비동기(Asynchronous) 작업을 수행할 때, 비동기 작업이 완료 되었음을을
     알리기 위한 방법으로 callback 함수(callback 매커니즘) 을 이용한다.






     ※ callback 매커니즘
           
<그림 2>는 전형적인 콜백 메커니즘을 보여주고 있다. 콜백 메커니즘의 순서로써 (1) 호출자는 콜백 메서드의 참조(함수 포인터)를 매개 변수로 하여 피호출 메서드를 호출한다(2) 피호출 메서드는 매개 변수로 전달된 콜백 메서드에 대한 참조를 필드와 같은 곳에 기록해 둔다.(3) 이제 콜백을 수행할 어떤 조건(이 조건은 다양할 수 있다)이 만족되면 ...(4) 기록해 둔 콜백 메서드 참조를 이용하여 콜백 메서드를 호출하게 된다.
물론 모든 콜백이 <그림 2>와 같은 순서를 따르는 것은 아니지만 많은 경우 이와 같은 시나리오를 따르는 것이 일반적이다. 콜백을 수행할 조건을 만족하는지 지속적으로 검사하는 과정이 필요하기 때문에 별도의 스레드를 이용하는 경우가 대부분이며, 콜백 메서드를 호출하는 스레드 역시 조건을 검사하는 스레드이기 때문에 콜백 메서드는 서로 다른 스레드에서 호출되는 것이 일반적이다. 이렇게 다중 스레드를 사용하기 때문에 비동기(asynchronous) 작업을 수행할 때 비동기 작업이 완료되었음을 알리기 위한 방법으로 콜백 메커니즘이 많이 사용되곤 한다.

출처 : http://imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=29268







   - callback 함수는 불려지는 쪽에서 부르는 쪽의 데이터를 참조 하거나 핸들링 하는 함수이다.
    다시 말해서 불려지는 쪽에서 부르는 쪽으 DATA를 참조하기 위한 교량 역할을 하는 함수가 callback 함수이다.




cf). callback 함수가 있다는 것을 알고 있었고, thread 가 있다는 것도 알고 간단한 사용법도 알았다.
    그런데 커다란 프로그램 에서는 정말... 복잡하지만 그 존재의 목적 대로 사용하고 있었다.
    이해가 안갔는데...  조금 정리가 되가는 것 같다.
    다음과 같은 경우이다.

1. Main Thread 에서  자료를 읽어 오는데 시간이 너무 오래 걸리는 거야...
   그래!! thread 를 이용하자!!

2. 생성한 Thread 에서 자료를 검색 해야 하는데 자료 검색 함수(메소드) 들이 MainThread 에 있는 거야...
3. 또 검색한 자료 값을 저장해야 하는데 그 변수 또한 Main Thread 에 있어.  Main Thread 와 자식 thread 간에는
   독립된 Stack 메모리를 사용하니까 변수를 고유 할 수 없고,
4. 그렇다고 전역변수를 사용하자니... 전역 변수의 사용은 지양해야해!!
5. Thread 에서 검색과정중 발생한 이벤트 역시 Main Thread 에 넘겨주고 싶어. 발생한 이벤트 마다
   Main Thread 가 다른 작업을 해주어야 하거든.
6. 그렇다고 Thread 에서 Main Thread 로 ::SendMessage() 함수를 사용 할 수는 없고,
   ::PostSendMessage() 는 안전하지 않으니 조금 사용하기가 그래.

7. callback 함수를 사용하자!!!
   callback 함수는 callback 함수가 불려지는 쪽(Thread)의 데이터를 callback 함수가 있는 곳(Main Thread)에서
   사용할 수가 있거든.




##

댓글 2개:

  1. 자료 감사히 읽었습니다. 그런데 다음 부분이 이해가 안 가는군요.
    "2. 생성한 Thread 에서 자료를 검색 해야 하는데 자료 검색 함수(메소드) 들이 MainThread 에 있는 거야..."

    변수는 스레드 스택에 종속적일 수 있지만 함수는 프로세스 전체에 포함될 뿐 스레드에 종속되지 않는 것으로 알고 있어서, 설명하시고자 한게 저 내용이 맞는지 궁금해서 글 남기고 갑니다.

    답글삭제
  2. 아!! 안녕하세요. 부족한 자료 읽어주셔서 감사합니다. 의문되는점 질문은 언제나 환영입니다. :)

    네 맞아요. 스레드 각각의 스택 메모리는 스레드에 종속적입니다. 함수는.. 스레드에 종속적이지 않을지라도 인스턴스 함수일 경우에는 스레드 안정적이지 않을것입니다. 스태틱 함수이면 안전할 수 있을지라도요 ^^

    답글삭제