2010-07-15 4 views
2

내가 추가 CFMachPortRef이가 GCD를 사용하여 수행 할 수 있습니다 내가 나 자신을 요구 한 스레드 CFRunLoop 이제GCD와 RunLoops 내 응용 프로그램에서

에 (CFMachPortCreateRunLoopSource를 통해)? 의 말을 대신 내 자신의 NSThread 산란과 파견의 runloop에 이벤트 포트를, CFRunLoopAddSource를 통해 자사의 실행 루프를 생성 CFRunLoopSourceRef을 추가하자?

나는 이것이 GCD의 내부 동작으로 인해 거의 작동하지 않을 것이라고 생각하지만 실제로는 모른다.

업데이트


I은 ​​이벤트 탭이 지금까지, 그러나 콜백 기능도있어 나 dispatch_source_event_handler 블록이라고합니다. 어떤 아이디어?

CFMachPortRef port = CGEventTapCreate(kCGSessionEventTap, 
             kCGHeadInsertEventTap, 
             opts, 
             desc_.eventMask, 
             _CGEventCallback, 
             self); 

// create dispatch source 
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, 
                CFMachPortGetPort(port), 
                0, 
                dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); 

// set event handler 
dispatch_source_set_event_handler(source, ^{ 
    printf("handle me!\n"); 
}); 

dispatch_resume(source); 
+0

'CFMachPort'는 마하 포트와 콜백을 결합합니다. GCD를 사용하여 Mach 포트를 모니터링하는 경우 콜백을 무시합니다. 이벤트 탭의 경우 콜백은 Core Graphics의 내부에 있으며 포트에서 Mach 메시지를 수신하고 디코딩 한 다음 * 콜백을 호출하는 등의 중요한 작업을 수행합니다. –

답변

2

실제로 GCD를 사용하여 dispatch_source_create() 기능을 사용하여 마하 포트를 모니터링 할 수 있습니다.

mach_port_t myPort; //assume you have this already 
dispatch_source_t portSource; 

portSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, myPort, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT)); 
dispatch_source_set_event_handler(portSource, ^(void) { //code for handling incoming message here }); 

dispatch_resume(portSource); 

메시지가 포트에 온다 때마다

, 당신은 이벤트 처리기로 전달하는 블록이 전화를받을해야하며,이 메시지를 처리 ​​할 수 ​​코드는 다음과 같을 것이다. 이 예제는 GCD가 제공 한 전역 대기열을 사용하여 메시지를 처리하지만 원하는 경우 사용자 정의 대기열을 만들 수 있습니다.

+0

(적어도 내 경우에는) 작동하지 않습니다. 위의 * 업데이트 * 섹션을 참조하십시오. –

+0

"이벤트 탭으로 이런 식으로 작동하지 않을 것"이라고 게시하면 답변을 수락 할 수 있습니다. –

+0

그 코드가 작동하지 않는 이유는 정확히 모르겠습니다. 실제로 GCD 이벤트 소스를 사용하지 않았습니다. Mach 포트 (다른 ​​유형의 GCD 소스를 사용 했음) 때문에 이벤트 탭용으로 만든 포트에 제한이 있는지 확실하지 않습니다. CFRunLoop 방식으로 시도 했습니까? 최소한 꼭지가 제대로 만들어지고 그 맥락에서 작동하는지 확인하십시오. –

0

GCD 큐의 알림 포트에서 콜백을 예약하려면 Runloop에 CFRunLoopAddSource 대신 IONotificationPortSetDispatchQueue을 사용할 수 있습니다.

예 :

IOServiceOpen(driver, mach_task_self(), 0, &connection); 

notifyPort = IONotificationPortCreate(kIOMasterPortDefault); 

IOServiceAddInterestNotification(
    notifyPort, 
    driver, 
    kIOGeneralInterest, 
    myCallback, 
    NULL, //refcon 
    &notificationObject 
); 

// Instead of this: 
// CFRunLoopAddSource(CFRunLoopGetCurrent(), 
//     IONotificationPortGetRunLoopSource(notifyPort), 
//     kCFRunLoopDefaultMode); 
// do this: 
IONotificationPortSetDispatchQueue(notifyPort, myQueue); 

이는 GCD 큐 myQueue 호출 할 수있는 myCallback() 핸들러의 원인이됩니다.

관련 문제