简易协程
#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;
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) {
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( ;; ) {
printf("CR_1 ----> 1\n");
crDelay(pCRCB, 3000);
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( ;; ) {
printf("CR_2 >>>> 4\n");
crDelay(pCRCB, 5000);
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