最近准备对一个小巧但又不失精妙和整体的脉络的协程调度器
动手了,为了能够深入的理解协程的调度机制和原理,特意分析了一个协程调度器的源码:coroutine
1.Coroutine源码分析
#pragma
//协程的四种不同的状态
#define COROUTINE_DEAD 0
#define COROUTINE_READY 1
#define COROUTINE_RUNNING 2
#define COROUTINE_SUSPEND 3
struct schedule; //调度器结构体
//协程执行函数
typedef void (*coroutine_func)(struct schedule *, void *ud);
//调度器的创建初始化和关闭
struct schedule * coroutine_open(void);
void coroutine_close(struct schedule *);
//协程创建到让出cpu挂起的整过程
int coroutine_new(struct schedule *, coroutine_func, void *ud);
void coroutine_resume(struct schedule *, int fd);
int coroutine_status(struct schedule *, int fd);
int coroutine_running(struct schedule *);
void coroutine_yield(struct schedule *);
#include "coroutine.h"
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <assert.h>
#include <stddef.h>
#include <string.h>
#define STACK_SIZE (1024 * 1024) //协程调度栈大小 1MB
#define DEFAULT_COROUNTINE 16 // 默认协程容量
struct coroutine;
struct schedule {
//调度器的结构
char stack[STACK_SIZE]; //调用栈,用来记录协程调用关系的栈
ucontext_t main; //协程的上下文
int nco; //当前协程存在的数量
int cap; //协程的容量
int running; //正在运行的协程“id”
struct coroutine **co; //协程控制块
};
struct coroutine {
coroutine_func func; //执行函数
void *ud; //函数参数
ucontext_t ctx; //协程上下文
struct schedule *sch; //调度器指针
ptrdiff_t cap;
ptrdiff_t size;
int status; //协程的状态
char *stack; //协程的运行栈
};
struct coroutine * //初始化创建协程
_co_new(struct schedule *S, coroutine_func func, void *ud) {
struct coroutine * co = malloc(sizeof(*co));
co->func = func;
co->ud = ud;
co->sch = S;
co->cap = 0;
co->size = 0;
co->status = COROUTINE_READY;
co->stack = NULL;
return co;
}
void //释放协程占有的资源
_co_delete(struct coroutine *co) {
free(co->stack);
free(co);
}
struct schedule * //初始化创建“协程调度器”
coroutine_open(void) {
struct schedule * S = malloc(sizeof(*S));
S->nco = 0;
S->cap = DEFAULT_COROUNTINE;
S->running = -1;
S->co = malloc(sizeof(struct coroutine