简易协程

简易协程

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

#define assert(x)  
typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned char uchar;
typedef unsigned long ulong;
// List
struct LNode {
	void *pData;
	struct LNode *pNext;
};
typedef LNode* PLNode;

struct List {
	uint uCount;
	PLNode pHead;
	PLNode pTail;
};
typedef List* PList;

PList pListContainer;

PLNode list_node_create() {
	PLNode pNode = (PLNode)malloc(sizeof(LNode));
	pNode->pData = NULL;
	pNode->pNext = NULL;
	return pNode;
}

void list_node_free(PLNode pNode) {
	//assert(pNode != NULL);
	free((void*)pNode);
}	

PList list_create() {
	PLNode pNode = list_node_create();
	PList pList = (PList)malloc(sizeof(List));
	pList->uCount = 0;
	pList->pHead = pNode;
	pList->pTail = pList->pHead;
	return pList;
}

void list_add(PList pList, void* pData) {
	assert(pList != NULL && pData != NULL);
	PLNode pNode = list_node_create();
	pNode->pData = pData;
	
	pList->uCount++;
	pList->pTail->pNext = pNode;
	pList->pTail = pNode;
}

PLNode list_first_node(PList pList) {
	PLNode p;
	p = pList->pHead;
	return p->pNext;
}

PLNode list_last_node(PList pList) {
	return pList->pTail;
}

void list_remove(PList pList, PLNode pNode) {
	PLNode p, q;
	assert(pList != NULL && pNde != NULL);
	p = pList->pHead;
	q= p->pNext;
	while(q!= NULL) {
		if(q == pNode) {
			p->pNext = q->pNext;
			if(q->pNext == NULL) {
				pList->pTail = p;
			}
			pList->uCount--;
			break;
		}
		p = p->pNext;
		q = p->pNext;
	}
}

PLNode list_find(PList pList, uint pos) {
	PLNode p, q;
	uint i = 0;
	assert(pList != NULL);
	p = pList->pHead;
	q = p->pNext;
	while(q != NULL) {
		if(i == pos) {
			return q;
		}
		++i;
		q = q->pNext;
	}
	return NULL;
}



#define INIT_STATE 0;

#define crStart(pCRCB) switch( ( (CRCB*)(pCRCB) )->uState ) { case 0:
#define crEnd() }

#define crYield(pCRCB) 											\
AddCoRoutineToRedayQueue((pCRCB));								\
( (CRCB*)(pCRCB) )->uState = (__LINE__*2); return; case (__LINE__*2):

#define crYield2(pCRCB) 										\
( (CRCB*)(pCRCB) )->uState = ((__LINE__*2)+1); return; case((__LINE__*2)+1):	

#define crDelay(pCRCB, ticksToDelay) 							\
if( (ticksToDelay) > 0) { 										\
	pCRCB->uValue = GetTickCount() + (ticksToDelay);			\
	AddCoRoutineToDelayQueue((pCRCB)); 							\
}																\
else {															\
	AddCoRoutineToRedayQueue((pCRCB));							\
}																\
crYield2((pCRCB));


typedef void* CoRoutineHandle;
typedef void (*CoRoutineFunc)(CoRoutineHandle, void*);
typedef struct CoRoutineControlBlock {
	CoRoutineFunc pCoRoutineFunction;
	void* param;
	uint uValue;
	ushort uState;
} CRCB;
static void InitCoRoutineLists();
static uint GetTickCount();
static void UpdateTicksCount();
static void AddCoRoutineToRedayQueue(CRCB*);
static void AddCoRoutineToDelayQueue(CRCB*);

CRCB *pCurrentCoRoutine = NULL;
static PList pCoRoutineDelayList = NULL;
static PList pCoRoutineReadyList = NULL;
static uint uLastTickCount= 0;
static uint uCurReadyIndexList = 0;
static uint uTicksCount = 0;

// 创建协程
ushort CoRoutineCreate(CoRoutineFunc pCoRountineFunc, void* param) {
CRCB *pCoRoutine;
	InitCoRoutineLists();
	pCoRoutine= (CRCB*)malloc(sizeof(CRCB));
	if(pCoRoutine) {
		pCoRoutine->uState = INIT_STATE;
		pCoRoutine->pCoRoutineFunction = pCoRountineFunc;
		pCoRoutine->param = param;
		pCoRoutine->uValue = 0;
		AddCoRoutineToRedayQueue(pCoRoutine);
		return 0;
	}
	return -1;
}

static void InitCoRoutineLists() {
	if(pCoRoutineReadyList == NULL) {
		pCoRoutineReadyList = list_create();
	}
	if(pCoRoutineDelayList == NULL) {
		pCoRoutineDelayList  = list_create();
	}
}

static uint GetTickCount() {
	return uTicksCount;
}

static void UpdateTicksCount() {
	++uTicksCount;
}

static void AddCoRoutineToRedayQueue(CRCB* pCoRoutine) {
	list_add(pCoRoutineReadyList , (void*)pCoRoutine);
}

static void AddCoRoutineToDelayQueue(CRCB* pCoRoutine) {
	list_add(pCoRoutineDelayList, (void*)pCoRoutine);
}

// 检测延迟列表是否超时
void CheckDelayedList() {
CRCB *pCRCB;
PLNode p, q;
PList pList ;
uint uTick;
	uTick= GetTickCount();
	pList = pCoRoutineDelayList;
	p = pList->pHead;
	q = p->pNext;
	while(q != NULL) {
		pCRCB = (CRCB*)(q->pData);
		if(uTick >= pCRCB->uValue){
			p->pNext= q->pNext;
			AddCoRoutineToRedayQueue(pCRCB);
			list_node_free(q);
			q = p->pNext;
		}
		else{
			p = q;
			q = q->pNext;
		}
	}
}

// 循环调度
void CoRoutineSchedule() {
CRCB *pCRCB;
PLNode pNode;
PList pList, pWaitList;
	UpdateTicksCount();
	CheckDelayedList();
	pList = pCoRoutineReadyList ;
	pNode = list_first_node(pList);
	if(pNode != NULL) {
		list_remove(pList, pNode);
		pCRCB = (CRCB*)(pNode->pData);
		if(pCRCB != NULL){
		    (pCRCB->pCoRoutineFunction)(pCRCB, pCRCB->param);
		}
	}
}


// 使用例子
void CallBackCoRoutine(CoRoutineHandle pHandler, void* param) {
CRCB *pCRCB;
	pCRCB = (CRCB*)pHandler;
	crStart(pCRCB);
	for( ;; ) {
	    // do some thing ...
    	printf("CR_1 ----> 1\n");
    	crDelay(pCRCB, 3000);
    	// do some thing ...
    	printf("CR_1 ----> 2\n");
    	crYield(pCRCB);
    	printf("CR_1 ----> 3\n");
    	crEnd();
	}
}

// 使用例子
void CallBackCoRoutine2(CoRoutineHandle pHandler, void* param) {
CRCB *pCRCB;
	pCRCB = (CRCB*)pHandler;
	crStart(pCRCB);
    for( ;; ) {
    	// do some thing ...
    	printf("CR_2 >>>> 4\n");
    	crDelay(pCRCB, 5000);
    	// do some thing ...
    	printf("CR_2 >>>> 5\n");
    	crYield(pCRCB);
    	printf("CR_2 >>>> 6\n");
    	crEnd();
    }
}

long get_time_ms() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

int main() {
    CoRoutineCreate(CallBackCoRoutine, 0);
    CoRoutineCreate(CallBackCoRoutine2, 0);
    long now, last_time;
    now = get_time_ms();
    last_time = now + 10 * 1000;
    while(now<last_time){
       CoRoutineSchedule();
       now = get_time_ms();
    }
    return 0;
}

输出结果:
CR_1 ----> 1
CR_2 >>>> 4
CR_1 ----> 2
CR_1 ----> 3
CR_1 ----> 1
CR_2 >>>> 5
CR_2 >>>> 6
CR_2 >>>> 4
CR_1 ----> 2
CR_1 ----> 3
CR_1 ----> 1
CR_1 ----> 2
CR_1 ----> 3
CR_1 ----> 1
CR_2 >>>> 5
CR_2 >>>> 6
CR_2 >>>> 4
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值