dispatch_apply 按照指定的次数将指定的任务提交到指定队列中,同步执行并等待所有任务完成后return
线程上下文:dispatch_thread_context_t dtctxt
基层嵌套:size_t nested = dtctxt ? dtctxt->dtc_apply_nesting : 0;
当前线程 dispatch_queue_t old_dq = _dispatch_queue_get_current();
源码:
void
dispatch_apply_f(size_t iterations, dispatch_queue_t _dq, void *ctxt,
void (*func)(void *, size_t))
{
if (unlikely(iterations == 0)) {
return;
}
//线程上下文
dispatch_thread_context_t dtctxt =
_dispatch_thread_context_find(_dispatch_apply_key);
//嵌套层数(递归调用)
size_t nested = dtctxt ? dtctxt->dtc_apply_nesting : 0;
//当前队列
dispatch_queue_t old_dq = _dispatch_queue_get_current();
//使用队列
dispatch_queue_t dq;
if (likely(_dq == DISPATCH_APPLY_AUTO)) {//判断参数_dq是否只自动分配
//那就放入根队列中
dq = _dispatch_apply_root_queue(old_dq)->_as_dq;
} else {
dq = _dq; // silence clang Nullability complaints
}
dispatch_qos_t qos = _dispatch_priority_qos(dq->dq_priority) ?:
_dispatch_priority_fallback_qos(dq->dq_priority);
if (unlikely(dq->do_targetq)) {
// if the queue passed-in is not a root queue, use the current QoS
// since the caller participates in the work anyway
qos = _dispatch_qos_from_pp(_dispatch_get_priority());
}
//获取到并发线程最大数量
int32_t thr_cnt = (int32_t)_dispatch_qos_max_parallelism(qos,
DISPATCH_MAX_PARALLELISM_ACTIVE);
if (likely(!nested)) {
nested = iterations;
} else {
//更新线程数量
thr_cnt = nested < (size_t)thr_cnt ? thr_cnt / (int32_t)nested : 1;
//更新嵌套层数
nested = nested < DISPATCH_APPLY_MAX && iterations < DISPATCH_APPLY_MAX
? nested * iterations : DISPATCH_APPLY_MAX;
}
//如果执行数量小于线程数,那就更新
if (iterations < (size_t)thr_cnt) {
thr_cnt = (int32_t)iterations;
}
//构造函数
struct dispatch_continuation_s dc = {
.dc_func = (void*)func,
.dc_ctxt = ctxt,
.dc_data = dq,
};
//创建一个持续调用空间
dispatch_apply_t da = (__typeof__(da))_dispatch_continuation_alloc();
da->da_index = 0;
da->da_todo = iterations;
da->da_iterations = iterations;
da->da_nested = nested;
da->da_thr_cnt = thr_cnt;
#if DISPATCH_INTROSPECTION
da->da_dc = _dispatch_continuation_alloc();
*da->da_dc = dc;
da->da_dc->dc_flags = DC_FLAG_ALLOCATED;
#else
da->da_dc = &dc;
#endif
da->da_flags = 0;
//同步执行
if (unlikely(dq->dq_width == 1 || thr_cnt <= 1)) {
return dispatch_sync_f(dq, da, _dispatch_apply_serial);
}
if (unlikely(dq->do_targetq)) {
if (unlikely(dq == old_dq)) {
return dispatch_sync_f(dq, da, _dispatch_apply_serial);
} else {
return dispatch_sync_f(dq, da, _dispatch_apply_redirect);
}
}
//递归调用
dispatch_thread_frame_s dtf;
_dispatch_thread_frame_push(&dtf, dq);
_dispatch_apply_f(upcast(dq)._dgq, da, _dispatch_apply_invoke);
_dispatch_thread_frame_pop(&dtf);
}
源码中dispatch_sync_f 那就不能在主队列中调用 会产生死锁
串行队列中,会抵消dispatch_apply的抵消迭代功能
并行队列中就如虎添翼
适用场景就是for不能办的很大很大数次循环