Why does dispatch_semaphore_wait() return YES all the time even when I'm not scrolling?

眉间皱痕 提交于 2019-12-11 07:55:57

问题


Brad Larson delivered a solution for the CADisplayLink freeze issue when scroll views are scrolling.

My OpenGL ES draw method is called by a CADisplayLink, and I tried Brad's technique but can't make it work. The core problem is that my OpenGL ES view is hosted by a UIScrollView, and when the UIScrollView scrolls, the CADisplayLink stops firing.

The technique Brad described is supposed to let the CADisplayLink continue to fire even during scrolling (by adding it to NSRunLoopCommonModes instead of the default runloop mode), and using a fancy semaphore trick the rendering callback is supposed to ensure that it doesn't render when UIKit is too occupied.

The problem is though that the semaphore trick prevents the rendering callback from drawing, no matter what.

First, I create the serial GCD queue and semaphore in the initWithFrame method of my OpenGL ES view like this (on the main thread):

frameRenderingQueue = dispatch_queue_create("com.mycompany.crw", DISPATCH_QUEUE_SERIAL);
frameRenderingSemaphore = dispatch_semaphore_create(1);

The display link is created and added to NSRunLoopCommonModes:

CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(renderFrame)];
[dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

The render callback performs Brad's technique:

- (void)renderFrame {
    if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) {
        NSLog(@"return"); // Gets called ALWAYS!
        return;
    }

    dispatch_async(drawingQueue, ^{
        @autoreleasepool {

            // OpenGL ES drawing code

            dispatch_semaphore_signal(frameRenderingSemaphore);
        }
    });
}

The dispatch_semaphore_wait function always returns YES and thus the render callback never renders. Even when I'm not scrolling.

I suppose that I missed something important here. Can someone point it out?

Edit: It seems to work only when I call dispatch_sync instead of dispatch_async, but according to Brad dispatch_async would give better performance here.


回答1:


I had to change the structure of the code to this:

- (void)renderFrame {
    dispatch_async(drawingQueue, ^{
        if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) {
            return;
        }

        @autoreleasepool {
            // Drawing code...
        }

        dispatch_semaphore_signal(frameRenderingSemaphore);
    });
}

After I restructured it this way, the dispatch_semaphore_wait call stopped returning YES all the time. I am not sure if this is effectively just disabling Brad's semaphore wait trick or not. But it works.



来源:https://stackoverflow.com/questions/12627581/why-does-dispatch-semaphore-wait-return-yes-all-the-time-even-when-im-not-scr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!