image.png
1: coobjc.h 內(nèi)聯(lián)函數(shù) 啟動協(xié)程
co_launch(^{
});
2.將block轉(zhuǎn)換成OC協(xié)程對象 COCoroutine.m 并且創(chuàng)建c的協(xié)程對象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
}
//設(shè)置 coroutine_t 為當(dāng)前COCoroutine屬性 _co
//c協(xié)程對象 coroutine_t 和 當(dāng)前 OC對象 COCoroutine 雙向引用
_co = co;
coroutine_setuserdata(co, (__bridge_retained void *)self, co_obj_dispose);
//將OC綁定到couserdata
co->userdata = userdata;
//設(shè)置釋放回調(diào)指針
co->userdata_dispose = ud_dispose;
3. 執(zhí)行協(xié)程 coobjc.h COCoroutine.m
return [co resume];
//將當(dāng)前任務(wù)放入CODispatch 隊(duì)列
3.1 self.dispatch dispatch_async_block:^{
//將協(xié)程添加到調(diào)度程序 進(jìn)入真正的協(xié)程處理方法
//跳轉(zhuǎn)到 coroutine_resume_im.m
coroutine_resume(self.co);
}];
3.1 //獲取當(dāng)前運(yùn)行的協(xié)程
coroutine_t *coroutine_self()
3.2 //獲取當(dāng)前運(yùn)行的協(xié)程調(diào)度器雪位。調(diào)度器跟協(xié)程關(guān)系超歌?
// 調(diào)度器由一個(gè)主協(xié)程箩张,co->is_scheduler = true;
// 調(diào)度器結(jié)構(gòu)
struct coroutine_scheduler {
coroutine_t *main_coroutine; //跟隨調(diào)度器同時(shí)生成的主協(xié)程
coroutine_t *running_coroutine; //當(dāng)前正在運(yùn)行的協(xié)程
coroutine_list_t coroutine_queue; //等待執(zhí)行的協(xié)程
};
//調(diào)度結(jié)構(gòu)體肆良,全局唯一 pthread_getspecific阿逃,pthread_setspecific實(shí)現(xiàn)
coroutine_scheduler_t
//里面有一個(gè)主協(xié)程
coroutine_scheduler_t *coroutine_scheduler_self(void)
4. coroutine_resume
4.1 //將當(dāng)前協(xié)程加入隊(duì)列
scheduler_queue_push(scheduler, co);
4.2 //如果當(dāng)前有正在運(yùn)行
if (scheduler->running_coroutine) {
//如果當(dāng)前有正在執(zhí)行的協(xié)程,插入到隊(duì)尾
scheduler_queue_push(scheduler, scheduler->running_coroutine);
//恢復(fù)當(dāng)前協(xié)程繼續(xù)執(zhí)行
coroutine_yield(scheduler->running_coroutine);
} else {
// 當(dāng)前調(diào)度沒有協(xié)程執(zhí)行时肿,恢復(fù)調(diào)度協(xié)程
// 調(diào)度主協(xié)程
coroutine_resume_im(co->scheduler->main_coroutine);
//主協(xié)程入口方法
// 從coroutine_queue pop一個(gè)協(xié)程出來執(zhí)行
coroutine_scheduler_main
}
5. //執(zhí)行協(xié)程
//由主協(xié)程的入口函數(shù)調(diào)度 協(xié)程
// COROUTINE_SUSPEND
void coroutine_resume_im(coroutine_t *co)
//創(chuàng)建pre_context
co->pre_context = malloc(sizeof(coroutine_ucontext_t));
//保存現(xiàn)場
//將當(dāng)前寄存器的值寫入co->pre_context
coroutine_getcontext(co->pre_context);
//創(chuàng)建co->context
co->context = calloc(1, sizeof(coroutine_ucontext_t));
//設(shè)置入口函數(shù)為pc
//設(shè)置sp,fp
coroutine_makecontext(co->context, (IMP)coroutine_main, co, (void *)co->stack_top);
//設(shè)置參數(shù)
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;
}
//調(diào)用匯編 執(zhí)行指令
coroutine_begin(co->context);
6. coroutine_yield
void coroutine_yield(coroutine_t *co){
//保存現(xiàn)場庇茫,將寄存器的值寫入oc->pre_context
//并且設(shè)置狀態(tài),下次可以恢復(fù)調(diào)度
co->status = COROUTINE_SUSPEND;
}
相關(guān)關(guān)鍵結(jié)構(gòu)體
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];
};
//協(xié)程先保存當(dāng)前寄存器的值到pre_context
//將寄存器的值寫入pre_context coroutine_ucontext_t
extern int coroutine_getcontext (coroutine_ucontext_t *__ucp);
//恢復(fù)現(xiàn)場螃成,將context的值讀入寄存器旦签,執(zhí)行入口函數(shù)
//由coroutine_scheduler_main 喚醒協(xié)程執(zhí)行
extern int coroutine_setcontext (coroutine_ucontext_t *__ucp);
//恢復(fù)現(xiàn)場,執(zhí)行入口函數(shù)
extern int coroutine_begin (coroutine_ucontext_t *__ucp);
//匯編指令找到pc
ldr x9, [x0, #0x100] // restore pc into lr
//跳轉(zhuǎn)到入口函數(shù)
ret x9