简易协程
#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