为什么需要调用dispatch_group_leave次数与dispatch_group_enter相同的次数? [英] Why is it necessary to call dispatch_group_leave the same number of times as dispatch_group_enter?

查看:447
本文介绍了为什么需要调用dispatch_group_leave次数与dispatch_group_enter相同的次数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的dispatch_group代码中,我使用dispatch_group_wait使一组Web服务调用超时. 问题,看来我需要计算调用多少次dispatch_group_enter,然后再调用相同数量的剩余dispatch_group_leave,以防某些Web服务调用永不返回,从而导致dispatch_group_enter与dispatch_group_leave的数目不相等.为什么?

In my dispatch_group code, I use dispatch_group_wait to time out a group of web service calls. Question, it seems like I would need to count how many times dispatch_group_enter is called and then call the same number of remaining dispatch_group_leave should some web service calls never return causing an unequal number of dispatch_group_enter vs dispatch_group_leave. Why?

我已经看到,如果在超时发生并触发dispatch_group_wait的情况下不这样做,则会发生崩溃.只要确保dispatch_group_enter/dispatch_group_leave与他们的通话次数匹配,崩溃就会消失.

I have seen crashes happening if I don't do this in the case when timeout happens and triggers dispatch_group_wait. The crash goes away as soon as make sure dispatch_group_enter/dispatch_group_leave match their call count.

dispatch_group_t group = dispatch_group_create();

for (...) {

  dispatch_group_enter(group);

  // Make backend call and upon return call dispatch_group_leave
  [self backendCallWithCompletionHandler:^(id results) {
     dispatch_group_leave(group);
  }

}

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_group_wait(self.group, dispatch_time(DISPATCH_TIME_NOW, 
(int64_t)(self.timeoutInterval * NSEC_PER_SEC)));
            dispatch_async(dispatch_get_main_queue(), ^{
                //execute stuff on main thread
                // call remaining dispatch_group_leave here if dispatch_group_enter and dispatch_group_leave count don't match?
            });
    });

推荐答案

非常有趣.我在OS X 10.9.4上使用Xcode 5.1.1测试了以下简单代码.

Quite interesting. I tested the following simple code with Xcode 5.1.1 on OS X 10.9.4.

/* test.m */
#include <dispatch/dispatch.h>

int main()
{
    {
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_enter(group);
        //dispatch_group_leave(group);
    }
    return 0;
}

使用ARC编译了Objective-C代码.

Compiled the Objective-C code with ARC.

$ clang -O0 -g -fobjc-arc a.m

执行程序.

$ ./a.out
illegal hardware instruction ./a.out

程序已崩溃.如果调用了dispatch_group_leave(group)(进入和离开均已平衡),则完全没有例外.使用lldb获取了崩溃的详细信息.

The program was crashed. If dispatch_group_leave(group) was called (enter and leave are all ballanced), there are no exceptions at all. Got the detail of the crash using lldb.

$ lldb a.out
Current executable set to 'a.out' (x86_64).
(lldb) run
Process 73482 launched: 'a.out' (x86_64)
Process 73482 stopped
* thread #1: tid = 0x3808a1, 0x00007fff87125287 libdispatch.dylib`_dispatch_semaphore_dispose + 55, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #0: 0x00007fff87125287 libdispatch.dylib`_dispatch_semaphore_dispose + 55
libdispatch.dylib`_dispatch_semaphore_dispose + 55:
-> 0x7fff87125287:  ud2    
   0x7fff87125289:  leaq   0x103b9(%rip), %rcx       ; "BUG IN LIBDISPATCH: flawed group/semaphore logic"
   0x7fff87125290:  movq   %rcx, -0x104f9b1f(%rip)   ; gCRAnnotations + 8
   0x7fff87125297:  ud2    
(lldb) 

在_dispatch_semaphore_dispose处发生了异常.幸运的是,我们可以在Apple OpenSource网站上阅读libdispatch源代码.看看 http://opensource.apple.com /source/libdispatch/libdispatch-339.92.1/src/semaphore.c

The exception was occurred at _dispatch_semaphore_dispose. We can luckily read libdispatch source code at Apple OpenSource site. Take a look at http://opensource.apple.com/source/libdispatch/libdispatch-339.92.1/src/semaphore.c

void
_dispatch_semaphore_dispose(dispatch_object_t dou)
{
    dispatch_semaphore_t dsema = dou._dsema;

    if (dsema->dsema_value < dsema->dsema_orig) {
        DISPATCH_CLIENT_CRASH(
                "Semaphore/group object deallocated while in use");
    }

根据此源代码,dispatch_group使用dispatch_semaphore.并且必须对调用信号/等待的dispatch_semaphore部队进行权衡.

According to this source code, dispatch_group uses dispatch_semaphore. And dispatch_semaphore forces calling signal/wait must be ballanced.

dispatch_semaphore_create手册:

dispatch_semaphore_create manual:

CAVEATS
     Unbalanced dispatch semaphores cannot be released.  For a given sema-
     phore, calls to dispatch_semaphore_signal() and dispatch_semaphore_wait()
     must be balanced before dispatch_release() is called on it.

因此,调用dispatch_group_enter和dispatch_group_leave也必须保持平衡.

Thus, calling dispatch_group_enter and dispatch_group_leave must be balanced as well.

这篇关于为什么需要调用dispatch_group_leave次数与dispatch_group_enter相同的次数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆