1: coobjc.h 内联函数 启动协程
co_launch(^{
});
2.将block转换成OC协程对象 COCoroutine.m 并且创建c的协程对象coroutine_t
COCoroutine *co = [COCoroutine coroutineWithBlock:block onQueue:nil];
coroutine_t *co = coroutine_create((void (*)(void *))co_exec);
if (stackSize > 0 && stackSize < 1024*1024) { // Max 1M
co->stack_size = (uint32_t)((stackSize % 16384 > 0) ? ((stackSize/16384 + 1) * 16384) : stackSize); // Align with 16kb
}
//设置 coroutine_t 为当前COCoroutine属性 _co
//c协程对象 coroutine_t 和 当前 OC对象 COCoroutine 双向引用
_co = co;
coroutine_setuserdata(co, (__bridge_retained void *)self, co_obj_dispose);
//将OC绑定到couserdata
co->userdata = userdata;
//设置释放回调指针
co->userdata_dispose = ud_dispose;
3. 执行协程 coobjc.h COCoroutine.m
return [co resume];
//将当前任务放入CODispatch 队列
3.1 self.dispatch dispatch_async_block:^{
//将协程添加到调度程序 进入真正的协程处理方法
//跳转到 coroutine_resume_im.m
coroutine_resume(self.co);
}];
3.1 //获取当前运行的协程
coroutine_t *coroutine_self()
3.2 //获取当前运行的协程调度器。调度器跟协程关系?
// 调度器由一个主协程,co->is_scheduler = true;
// 调度器结构
struct coroutine_scheduler {
coroutine_t *main_coroutine; //跟随调度器同时生成的主协程
coroutine_t *running_coroutine; //当前正在运行的协程
coroutine_list_t coroutine_queue; //等待执行的协程
};
//调度结构体,全局唯一 pthread_getspecific,pthread_setspecific实现
coroutine_scheduler_t
//里面有一个主协程
coroutine_scheduler_t *coroutine_scheduler_self(void)
4. coroutine_resume
4.1 //将当前协程加入队列
scheduler_queue_push(scheduler, co);
4.2 //如果当前有正在运行
if (scheduler->running_coroutine) {
//如果当前有正在执行的协程,插入到队尾
scheduler_queue_push(scheduler, scheduler->running_coroutine);
//恢复当前协程继续执行
coroutine_yield(scheduler->running_coroutine);
} else {
// 当前调度没有协程执行,恢复调度协程
// 调度主协程
coroutine_resume_im(co->scheduler->main_coroutine);
//主协程入口方法
// 从coroutine_queue pop一个协程出来执行
coroutine_scheduler_main
}
5. //执行协程
//由主协程的入口函数调度 协程
// COROUTINE_SUSPEND
void coroutine_resume_im(coroutine_t *co)
//创建pre_context
co->pre_context = malloc(sizeof(coroutine_ucontext_t));
//保存现场
//将当前寄存器的值写入co->pre_context
coroutine_getcontext(co->pre_context);
//创建co->context
co->context = calloc(1, sizeof(coroutine_ucontext_t));
//设置入口函数为pc
//设置sp,fp
coroutine_makecontext(co->context, (IMP)coroutine_main, co, (void *)co->stack_top);
//设置参数
void coroutine_makecontext (coroutine_ucontext_t *ctx, IMP func, void *arg, void *stackTop)
{
struct coroutine_ucontext_re *uctx = (struct coroutine_ucontext_re *)ctx;
uintptr_t stackBegin = (uintptr_t)stackTop - sizeof(uintptr_t);
uctx->GR.__fp = stackBegin;
uctx->GR.__sp = stackBegin;
uctx->GR.__x[0] = (uintptr_t)arg;
uctx->GR.__pc = (uintptr_t)func;
}
//调用汇编 执行指令
coroutine_begin(co->context);
6. coroutine_yield
void coroutine_yield(coroutine_t *co){
//保存现场,将寄存器的值写入oc->pre_context
//并且设置状态,下次可以恢复调度
co->status = COROUTINE_SUSPEND;
}
相关关键结构体
typedef struct coroutine_ucontext {
uint64_t data[100];
} coroutine_ucontext_t;
struct coroutine_ucontext_re {
struct GPRs {
uint64_t __x[29]; // x0-x28
uint64_t __fp; // Frame pointer x29
uint64_t __lr; // Link register x30
uint64_t __sp; // Stack pointer x31
uint64_t __pc; // Program counter
uint64_t padding; // 16-byte align, for cpsr
} GR;
double VR[32];
};
//协程先保存当前寄存器的值到pre_context
//将寄存器的值写入pre_context coroutine_ucontext_t
extern int coroutine_getcontext (coroutine_ucontext_t *__ucp);
//恢复现场,将context的值读入寄存器,执行入口函数
//由coroutine_scheduler_main 唤醒协程执行
extern int coroutine_setcontext (coroutine_ucontext_t *__ucp);
//恢复现场,执行入口函数
extern int coroutine_begin (coroutine_ucontext_t *__ucp);
//汇编指令找到pc
ldr x9, [x0, #0x100] // restore pc into lr
//跳转到入口函数
ret x9