1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | #include <stdio.h> #include <time.h> #include <stdlib.h> #include <signal.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <arpa/inet.h> #include <fcntl.h> #include <unistd.h> #include <pthread.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #if 1 #define DPRINTF(format, ...) do { \ printf(format, ## __VA_ARGS__); \ } while(0) #else #define DPRINTF(format, ...) do {} while(0) #endif #define SM_CONTINUE 1 #define SM_STOP 0 #define MAX_THREAD 10 enum STATE { ST_NULL=0, ST_1, ST_2, ST_MAX, }; struct STATE_INFO { int threadIndex; enum STATE state; char wait; }; struct STATE_MACHINE { enum STATE state; int (*stFunc) (struct STATE_INFO *sInfo); }; int st1 (struct STATE_INFO *sInfo); int st2 (struct STATE_INFO *sInfo); struct STATE_MACHINE statemachineList[ST_MAX] = { {ST_1, st1}, {ST_2, st2}, }; pthread_t tid[MAX_THREAD]={0}; void threadWaitReady(struct STATE_INFO *sInfo) { while (sInfo->wait) { usleep(100); } } int statemachineFindIndexByState(enum STATE state) { int i, index=-1; int stCount = sizeof(statemachineList)/sizeof(struct STATE_MACHINE); for(i=0; i<stCount; i++) { if (statemachineList[i].state == state) { index = i; i = stCount; } } return index; } void * statemachineMain(void *arg) { struct STATE_INFO sInfo, *ssInfo; int stateIndex; char resume=SM_CONTINUE; pthread_detach(pthread_self()); memcpy(&sInfo, arg, sizeof(sInfo)); ssInfo = arg; ssInfo->wait = 0; DPRINTF("t[%d] [%s] start statemachine with state %d\n", sInfo.threadIndex, __func__, sInfo.state); while (resume != SM_STOP) { stateIndex = statemachineFindIndexByState(sInfo.state); if (-1 == stateIndex) { resume = SM_STOP; } else { if (statemachineList[stateIndex].stFunc) { resume = statemachineList[stateIndex].stFunc(&sInfo); } else { resume = SM_STOP; DPRINTF("t[%d] [%s] state %d without callback function\n", sInfo.threadIndex, __func__, sInfo.state); } } } tid[sInfo.threadIndex] = 0; pthread_exit(NULL); } int threadFindFree (void) { int i, retval=-1; for (i=0; i<MAX_THREAD; i++) { if (0 == tid[i]) { retval = i; break; } } return retval; } int main(int argc, char *argv[]) { struct STATE_INFO sInfo; int i, tIndex; i=0; while(1) { bzero(&sInfo, sizeof(sInfo)); sInfo.threadIndex = threadFindFree(); if (-1 != sInfo.threadIndex) { ++i; i %= ST_MAX; sInfo.state = i; sInfo.wait = 1; if(pthread_create(&tid[sInfo.threadIndex], NULL, statemachineMain, (void*) &sInfo) != 0 ) { tid[sInfo.threadIndex] = 0; DPRINTF("t[%d] [%s] Failed to create thread\n", sInfo.threadIndex , __func__); } else { threadWaitReady(&sInfo); } } usleep(1234567); } } int st1 (struct STATE_INFO *sInfo) { DPRINTF("t[%d] [%s]\n", sInfo->threadIndex, __func__); sInfo->state = ST_2; usleep(1000000); return SM_CONTINUE; } int st2 (struct STATE_INFO *sInfo) { DPRINTF("t[%d] [%s]\n", sInfo->threadIndex, __func__); sInfo->state = ST_1; usleep(2000000); return SM_CONTINUE; } |
2020/06/09
[C] Simple state machine with pthread support
訂閱:
文章 (Atom)