├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── bp.h ├── demo.c └── demo.gif /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | *.c linguist-language=C 3 | *.h linguist-language=C 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | a lightweight coroutine library named lw_coroutine 4 | 5 | Copyright (c) 2018 xiaoliang<1296283984@qq.com>. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lw_coroutine 2 | ============ 3 | 仅一个bp.h文件,它类似于protothread,但采用了不同的实现机制,它使用switch-goto实现,相比protothread有如下优势: 4 | 5 | * 最低的资源占用,仅使用1字节进行状态保存 6 | * bp支持在switch中进行yield, 而protothread不支持(仅gcc编译器支持,但移植性差) 7 | * bp有更高效的跳转能力,因为bp中的case是从0连续的,因此可以被优化成最高效的跳转表,而protothread使用行号,具有随机性,因此protothread的跳转性能较差 8 | * bp的断点号是非常容易识别的,因此可以在bp_begin之前可用于判断当前yield的位置,以实现特殊的需求。而protothread使用的行号是不可识别的,因此其状态信息不能在begin之前被解读出来。 9 | * bp更精简,使用时仅依赖一个状态变量,因此可以被用于任何的异步回调中,以实现协程。 10 | 11 | 用例: 12 | ----- 13 | 14 | ```c 15 | #include "bp.h" 16 | #include 17 | #include 18 | 19 | typedef struct 20 | { 21 | /* resource */ 22 | short res; 23 | 24 | /* consumer coroutine breakpoint */ 25 | unsigned char consumer_bp; 26 | 27 | /* produce coroutine breakpoint */ 28 | unsigned char producer_bp; 29 | } res_t; 30 | 31 | #define TRUE 1 32 | #define FALSE (!TRUE) 33 | 34 | int consumer(res_t *res) 35 | { 36 | /* bpd coroutine default breakpoint pointer */ 37 | unsigned char *bpd = &res->consumer_bp; 38 | 39 | /* coroutine begin */ 40 | bpd_begin(2); 41 | 42 | while (1) 43 | { 44 | /* wait number of resource > 0 */ 45 | while (res->res <= 0) 46 | { 47 | bpd_yield(1) FALSE; 48 | } 49 | 50 | /* consume */ 51 | res->res--; 52 | printf("consume a resource, number of res:%d\n", res->res); 53 | 54 | /* wait next consume */ 55 | bpd_yield(2) TRUE; 56 | } 57 | 58 | /* coroutine end */ 59 | bpd_end(); 60 | } 61 | 62 | int producer(res_t *res) 63 | { 64 | /* bpd coroutine default breakpoint pointer */ 65 | unsigned char *bpd = &res->producer_bp; 66 | 67 | /* coroutine begin */ 68 | bpd_begin(2); 69 | 70 | while (1) 71 | { 72 | /* wait number of resource < 30 */ 73 | while (res->res >= 30) 74 | { 75 | bpd_yield(1) FALSE; 76 | } 77 | 78 | /* produce */ 79 | res->res++; 80 | printf("produce a resource, number of res:%d\n", res->res); 81 | 82 | /* wait next produce */ 83 | bpd_yield(2) TRUE; 84 | } 85 | 86 | /* coroutine end */ 87 | bpd_end(); 88 | } 89 | 90 | int main() 91 | { 92 | res_t res = {0, BP_INIT_VAL, BP_INIT_VAL}; 93 | int nrand; 94 | 95 | /* initialize random */ 96 | srand(122); 97 | 98 | /* randomly produce and consume */ 99 | while (1) 100 | { 101 | nrand = rand() % 16; 102 | while (nrand--) 103 | { 104 | if (consumer(&res) == FALSE) 105 | break; 106 | } 107 | 108 | nrand = rand() % 16; 109 | while (nrand--) 110 | { 111 | if (producer(&res) == FALSE) 112 | break; 113 | } 114 | } 115 | 116 | return 0; 117 | } 118 | ``` 119 | 示例动画: 120 | 121 | 122 | lw_coroutine 123 | ============ 124 | There is only one bp.h file, which is similar to protothread, but uses a different implementation mechanism. It is implemented using switch-goto and has the following advantages over protothread: 125 | 126 | * Lowest resource usage, use only 1 byte for state preservation 127 | * bp supports yield in switch, but protothread does not support (only gcc compiler support, but poor portability) 128 | * bp has a more efficient ability to jump, because the case in bp is continuous from 0, so it can be optimized to the most efficient jump table, and protothread use the line number, with randomness, so the protothread jump performance is poor 129 | * The breakpoint number of bp is very easy to identify, so it can be used to determine the current yield position before bp_begin to achieve special needs. The line number used by protothread is unrecognizable, so its status information cannot be interpreted before PT_BEGIN. 130 | * The bp is more streamlined, using only one state variable when used, so it can be used in any asynchronous callback to implement coroutines. 131 | 132 | Usage: 133 | ------- 134 | 135 | ```c 136 | #include "bp.h" 137 | #include 138 | #include 139 | 140 | typedef struct 141 | { 142 | /* resource */ 143 | short res; 144 | 145 | /* consumer coroutine breakpoint */ 146 | unsigned char consumer_bp; 147 | 148 | /* produce coroutine breakpoint */ 149 | unsigned char producer_bp; 150 | } res_t; 151 | 152 | #define TRUE 1 153 | #define FALSE (!TRUE) 154 | 155 | int consumer(res_t *res) 156 | { 157 | /* bpd coroutine default breakpoint pointer */ 158 | unsigned char *bpd = &res->consumer_bp; 159 | 160 | /* coroutine begin */ 161 | bpd_begin(2); 162 | 163 | while (1) 164 | { 165 | /* wait number of resource > 0 */ 166 | while (res->res <= 0) 167 | { 168 | bpd_yield(1) FALSE; 169 | } 170 | 171 | /* consume */ 172 | res->res--; 173 | printf("consume a resource, number of res:%d\n", res->res); 174 | 175 | /* wait next consume */ 176 | bpd_yield(2) TRUE; 177 | } 178 | 179 | /* coroutine end */ 180 | bpd_end(); 181 | } 182 | 183 | int producer(res_t *res) 184 | { 185 | /* bpd coroutine default breakpoint pointer */ 186 | unsigned char *bpd = &res->producer_bp; 187 | 188 | /* coroutine begin */ 189 | bpd_begin(2); 190 | 191 | while (1) 192 | { 193 | /* wait number of resource < 30 */ 194 | while (res->res >= 30) 195 | { 196 | bpd_yield(1) FALSE; 197 | } 198 | 199 | /* produce */ 200 | res->res++; 201 | printf("produce a resource, number of res:%d\n", res->res); 202 | 203 | /* wait next produce */ 204 | bpd_yield(2) TRUE; 205 | } 206 | 207 | /* coroutine end */ 208 | bpd_end(); 209 | } 210 | 211 | int main() 212 | { 213 | res_t res = {0, BP_INIT_VAL, BP_INIT_VAL}; 214 | int nrand; 215 | 216 | /* initialize random */ 217 | srand(122); 218 | 219 | /* randomly produce and consume */ 220 | while (1) 221 | { 222 | nrand = rand() % 16; 223 | while (nrand--) 224 | { 225 | if (consumer(&res) == FALSE) 226 | break; 227 | } 228 | 229 | nrand = rand() % 16; 230 | while (nrand--) 231 | { 232 | if (producer(&res) == FALSE) 233 | break; 234 | } 235 | } 236 | 237 | return 0; 238 | } 239 | ``` 240 | -------------------------------------------------------------------------------- /bp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 xiaoliang<1296283984@qq.com>. 3 | */ 4 | 5 | /************************************************************************ 6 | * BP (breakpoint), a programming method that sets a breakpoint 7 | * in a function and resumes on the next call 8 | * BP(breakpoint),一种可在函数中设置断点,且在下次调用时恢复的编程方式 9 | ************************************************************************ 10 | */ 11 | 12 | /************************************************************************ 13 |  * BP series usage: 14 |  * 15 |  * //use static variables or external data structures to save function breakpoints 16 |  * static uint8_t bp = BP_INIT_VAL; 17 | * static uint8_t *bpd = &bp; 18 |  * 19 |  * //intercept callback before bp_begin and check breakpoint status 20 |  * if (bp == 1) //bp is currently at breakpoint 1 21 |  * { 22 |  * //check the status and events 23 |  * if (event != timer1) 24 |  * { 25 |  * //Reject this event 26 |  * return ; 27 |  * } 28 |  * } 29 |  * 30 | * //start a coroutine with two breakpoints 31 |  * bpd_begin(2) 32 |  * 33 |  * while (1) 34 |  * { 35 |  * //set its own callback, trigger the next call 36 |  * timer_start(timer1, self_callback, 1000); 37 |  * 38 |  * //active return, and restore the current position on the next callback 39 |  * bpd_yield(1); 40 |  * 41 |  * //the timer arrives that turned on the led 42 |  * led_on(); 43 |  * 44 |  * //set its own callback, trigger the next call 45 |  * timer_start(timer2, self_callback, 1000); 46 |  * 47 |  * //active return, and restore the current position on the next callback 48 |  * bpd_yield(2); 49 |  * 50 |  * //the timer arrives that turned off the led 51 |  * led_off(); 52 |  * 53 |  * } 54 |  * 55 |  * bp_end(bp); 56 | * 57 | ************************************************************************ 58 | */ 59 | 60 | /************************************************************************ 61 | * 用法说明: 62 | * BP系列用法: 63 | * 64 | * //使用静态变量或者外部数据结构保存函数的断点 65 | * static uint8_t bp = BP_INIT_VAL; 66 | * static uint8_t *bpd = &bp; 67 | * 68 | * //在bp_begin之前可以拦截回调,并检查断点状态 69 | * if (bp == 1) //bp当前处于断点1 70 | * { 71 | * //对状态与事件进行检查 72 | * if (event != timer1) 73 | * { 74 | * //拒绝该事件 75 | * return ; 76 | * } 77 | * } 78 | * 79 | * //开始包含2个断点的协程 80 | * bpd_begin(2) 81 | * 82 | * while (1) 83 | * { 84 | * //设置自身回调,触发下次调用 85 | * timer_start(timer1, self_callback, 1000); 86 | * 87 | * //主动返回,并在下次回调时恢复当前位置 88 | * bpd_yield(1); 89 | * 90 | * //定时器到达,打开LED 91 | * led_on(); 92 | * 93 | * //设置自身回调,触发下次调用 94 | * timer_start(timer2, self_callback, 1000); 95 | * 96 | * //主动返回,并在下次回调时恢复当前位置 97 | * bpd_yield(2); 98 | * 99 | * //定时器到达,关闭LED 100 | * led_off(); 101 | * } 102 | * 103 | * bp_end(bp); 104 | * 105 | ************************************************************************ 106 | */ 107 | 108 | #ifndef __BP_H__ 109 | #define __BP_H__ 110 | 111 | /************************************************************************* 112 | * BP macro build 113 | * BP 宏构造 114 | ************************************************************************* 115 | */ 116 | 117 | /* BP macro connection, and fully expand */ 118 | /* BP宏连接,并完全展开 */ 119 | #define __BP_CAT(x, y) __BP_CAT1(x, y) 120 | #define __BP_CAT1(x, y) x##y 121 | 122 | /* BP label prefix definition */ 123 | /* BP标号前缀定义 */ 124 | #define BP_LABEL_PREFIX label_bp_ 125 | 126 | /* BP label with N suffix */ 127 | /* 以N为后缀的BP标签 */ 128 | #define BP_LABEL_N(n) __BP_CAT(BP_LABEL_PREFIX, n) 129 | 130 | /* BP start label */ 131 | /* BP开始标签 */ 132 | #define BP_LABEL_START BP_LABEL_N(0) 133 | 134 | /* BP end label */ 135 | /* BP结束标签 */ 136 | #define BP_LABEL_END BP_LABEL_N(end) 137 | 138 | /* the head of the BP_BEGIN, 139 | * the switch-goto statement block */ 140 | /* BP_BEGIN的头部,switch-goto语句块 */ 141 | #define __BP_HEADER(bp) do { \ 142 | switch ((bp)) \ 143 | { \ 144 | 145 | /* the tail of the BP_BEGIN, 146 | * the switch-goto statement block */ 147 | /* BP_BEGIN的尾部,switch-goto语句块 */ 148 | #define __BP_TAIL default: \ 149 | goto BP_LABEL_END; \ 150 | } \ 151 | BP_LABEL_START:; \ 152 | } while (0) \ 153 | 154 | /* the block part of the case statement for BP_BEGIN */ 155 | /* BP_BEGIN的case语句块部分 */ 156 | #define __BP_CASE0 case 0: goto BP_LABEL_START; 157 | #define __BP_CASE1 __BP_CASE0 case 1: goto BP_LABEL_N(1); 158 | #define __BP_CASE2 __BP_CASE1 case 2: goto BP_LABEL_N(2); 159 | #define __BP_CASE3 __BP_CASE2 case 3: goto BP_LABEL_N(3); 160 | #define __BP_CASE4 __BP_CASE3 case 4: goto BP_LABEL_N(4); 161 | #define __BP_CASE5 __BP_CASE4 case 5: goto BP_LABEL_N(5); 162 | #define __BP_CASE6 __BP_CASE5 case 6: goto BP_LABEL_N(6); 163 | #define __BP_CASE7 __BP_CASE6 case 7: goto BP_LABEL_N(7); 164 | #define __BP_CASE8 __BP_CASE7 case 8: goto BP_LABEL_N(8); 165 | #define __BP_CASE9 __BP_CASE8 case 9: goto BP_LABEL_N(9); 166 | #define __BP_CASE10 __BP_CASE9 case 10: goto BP_LABEL_N(10); 167 | #define __BP_CASE11 __BP_CASE10 case 11: goto BP_LABEL_N(11); 168 | #define __BP_CASE12 __BP_CASE11 case 12: goto BP_LABEL_N(12); 169 | #define __BP_CASE13 __BP_CASE12 case 13: goto BP_LABEL_N(13); 170 | #define __BP_CASE14 __BP_CASE13 case 14: goto BP_LABEL_N(14); 171 | #define __BP_CASE15 __BP_CASE14 case 15: goto BP_LABEL_N(15); 172 | #define __BP_CASE16 __BP_CASE15 case 16: goto BP_LABEL_N(16); 173 | #define __BP_CASE17 __BP_CASE16 case 17: goto BP_LABEL_N(17); 174 | #define __BP_CASE18 __BP_CASE17 case 18: goto BP_LABEL_N(18); 175 | #define __BP_CASE19 __BP_CASE18 case 19: goto BP_LABEL_N(19); 176 | #define __BP_CASE20 __BP_CASE19 case 20: goto BP_LABEL_N(20); 177 | #define __BP_CASE21 __BP_CASE20 case 21: goto BP_LABEL_N(21); 178 | #define __BP_CASE22 __BP_CASE21 case 22: goto BP_LABEL_N(22); 179 | #define __BP_CASE23 __BP_CASE22 case 23: goto BP_LABEL_N(23); 180 | #define __BP_CASE24 __BP_CASE23 case 24: goto BP_LABEL_N(24); 181 | #define __BP_CASE25 __BP_CASE24 case 25: goto BP_LABEL_N(25); 182 | #define __BP_CASE26 __BP_CASE25 case 26: goto BP_LABEL_N(26); 183 | #define __BP_CASE27 __BP_CASE26 case 27: goto BP_LABEL_N(27); 184 | #define __BP_CASE28 __BP_CASE27 case 28: goto BP_LABEL_N(28); 185 | #define __BP_CASE29 __BP_CASE28 case 29: goto BP_LABEL_N(29); 186 | #define __BP_CASE30 __BP_CASE29 case 30: goto BP_LABEL_N(30); 187 | #define __BP_CASE31 __BP_CASE30 case 31: goto BP_LABEL_N(31); 188 | #define __BP_CASE32 __BP_CASE31 case 32: goto BP_LABEL_N(32); 189 | #define __BP_CASE33 __BP_CASE32 case 33: goto BP_LABEL_N(33); 190 | #define __BP_CASE34 __BP_CASE33 case 34: goto BP_LABEL_N(34); 191 | #define __BP_CASE35 __BP_CASE34 case 35: goto BP_LABEL_N(35); 192 | #define __BP_CASE36 __BP_CASE35 case 36: goto BP_LABEL_N(36); 193 | #define __BP_CASE37 __BP_CASE36 case 37: goto BP_LABEL_N(37); 194 | #define __BP_CASE38 __BP_CASE37 case 38: goto BP_LABEL_N(38); 195 | #define __BP_CASE39 __BP_CASE38 case 39: goto BP_LABEL_N(39); 196 | #define __BP_CASE40 __BP_CASE39 case 40: goto BP_LABEL_N(40); 197 | #define __BP_CASE41 __BP_CASE40 case 41: goto BP_LABEL_N(41); 198 | #define __BP_CASE42 __BP_CASE41 case 42: goto BP_LABEL_N(42); 199 | #define __BP_CASE43 __BP_CASE42 case 43: goto BP_LABEL_N(43); 200 | #define __BP_CASE44 __BP_CASE43 case 44: goto BP_LABEL_N(44); 201 | #define __BP_CASE45 __BP_CASE44 case 45: goto BP_LABEL_N(45); 202 | #define __BP_CASE46 __BP_CASE45 case 46: goto BP_LABEL_N(46); 203 | #define __BP_CASE47 __BP_CASE46 case 47: goto BP_LABEL_N(47); 204 | #define __BP_CASE48 __BP_CASE47 case 48: goto BP_LABEL_N(48); 205 | #define __BP_CASE49 __BP_CASE48 case 49: goto BP_LABEL_N(49); 206 | #define __BP_CASE50 __BP_CASE49 case 50: goto BP_LABEL_N(50); 207 | #define __BP_CASE51 __BP_CASE50 case 51: goto BP_LABEL_N(51); 208 | #define __BP_CASE52 __BP_CASE51 case 52: goto BP_LABEL_N(52); 209 | #define __BP_CASE53 __BP_CASE52 case 53: goto BP_LABEL_N(53); 210 | #define __BP_CASE54 __BP_CASE53 case 54: goto BP_LABEL_N(54); 211 | #define __BP_CASE55 __BP_CASE54 case 55: goto BP_LABEL_N(55); 212 | #define __BP_CASE56 __BP_CASE55 case 56: goto BP_LABEL_N(56); 213 | #define __BP_CASE57 __BP_CASE56 case 57: goto BP_LABEL_N(57); 214 | #define __BP_CASE58 __BP_CASE57 case 58: goto BP_LABEL_N(58); 215 | #define __BP_CASE59 __BP_CASE58 case 59: goto BP_LABEL_N(59); 216 | #define __BP_CASE60 __BP_CASE59 case 60: goto BP_LABEL_N(60); 217 | #define __BP_CASE61 __BP_CASE60 case 61: goto BP_LABEL_N(61); 218 | #define __BP_CASE62 __BP_CASE61 case 62: goto BP_LABEL_N(62); 219 | #define __BP_CASE63 __BP_CASE62 case 63: goto BP_LABEL_N(63); 220 | #define __BP_CASE64 __BP_CASE63 case 64: goto BP_LABEL_N(64); 221 | #define __BP_CASE65 __BP_CASE64 case 65: goto BP_LABEL_N(65); 222 | #define __BP_CASE66 __BP_CASE65 case 66: goto BP_LABEL_N(66); 223 | #define __BP_CASE67 __BP_CASE66 case 67: goto BP_LABEL_N(67); 224 | #define __BP_CASE68 __BP_CASE67 case 68: goto BP_LABEL_N(68); 225 | #define __BP_CASE69 __BP_CASE68 case 69: goto BP_LABEL_N(69); 226 | #define __BP_CASE70 __BP_CASE69 case 70: goto BP_LABEL_N(70); 227 | #define __BP_CASE71 __BP_CASE70 case 71: goto BP_LABEL_N(71); 228 | #define __BP_CASE72 __BP_CASE71 case 72: goto BP_LABEL_N(72); 229 | #define __BP_CASE73 __BP_CASE72 case 73: goto BP_LABEL_N(73); 230 | #define __BP_CASE74 __BP_CASE73 case 74: goto BP_LABEL_N(74); 231 | #define __BP_CASE75 __BP_CASE74 case 75: goto BP_LABEL_N(75); 232 | #define __BP_CASE76 __BP_CASE75 case 76: goto BP_LABEL_N(76); 233 | #define __BP_CASE77 __BP_CASE76 case 77: goto BP_LABEL_N(77); 234 | #define __BP_CASE78 __BP_CASE77 case 78: goto BP_LABEL_N(78); 235 | #define __BP_CASE79 __BP_CASE78 case 79: goto BP_LABEL_N(79); 236 | #define __BP_CASE80 __BP_CASE79 case 80: goto BP_LABEL_N(80); 237 | #define __BP_CASE81 __BP_CASE80 case 81: goto BP_LABEL_N(81); 238 | #define __BP_CASE82 __BP_CASE81 case 82: goto BP_LABEL_N(82); 239 | #define __BP_CASE83 __BP_CASE82 case 83: goto BP_LABEL_N(83); 240 | #define __BP_CASE84 __BP_CASE83 case 84: goto BP_LABEL_N(84); 241 | #define __BP_CASE85 __BP_CASE84 case 85: goto BP_LABEL_N(85); 242 | #define __BP_CASE86 __BP_CASE85 case 86: goto BP_LABEL_N(86); 243 | #define __BP_CASE87 __BP_CASE86 case 87: goto BP_LABEL_N(87); 244 | #define __BP_CASE88 __BP_CASE87 case 88: goto BP_LABEL_N(88); 245 | #define __BP_CASE89 __BP_CASE88 case 89: goto BP_LABEL_N(89); 246 | #define __BP_CASE90 __BP_CASE89 case 90: goto BP_LABEL_N(90); 247 | #define __BP_CASE91 __BP_CASE90 case 91: goto BP_LABEL_N(91); 248 | #define __BP_CASE92 __BP_CASE91 case 92: goto BP_LABEL_N(92); 249 | #define __BP_CASE93 __BP_CASE92 case 93: goto BP_LABEL_N(93); 250 | #define __BP_CASE94 __BP_CASE93 case 94: goto BP_LABEL_N(94); 251 | #define __BP_CASE95 __BP_CASE94 case 95: goto BP_LABEL_N(95); 252 | #define __BP_CASE96 __BP_CASE95 case 96: goto BP_LABEL_N(96); 253 | #define __BP_CASE97 __BP_CASE96 case 97: goto BP_LABEL_N(97); 254 | #define __BP_CASE98 __BP_CASE97 case 98: goto BP_LABEL_N(98); 255 | #define __BP_CASE99 __BP_CASE98 case 99: goto BP_LABEL_N(99); 256 | #define __BP_CASE100 __BP_CASE99 case 100: goto BP_LABEL_N(100); 257 | #define __BP_CASE101 __BP_CASE100 case 101: goto BP_LABEL_N(101); 258 | #define __BP_CASE102 __BP_CASE101 case 102: goto BP_LABEL_N(102); 259 | #define __BP_CASE103 __BP_CASE102 case 103: goto BP_LABEL_N(103); 260 | #define __BP_CASE104 __BP_CASE103 case 104: goto BP_LABEL_N(104); 261 | #define __BP_CASE105 __BP_CASE104 case 105: goto BP_LABEL_N(105); 262 | #define __BP_CASE106 __BP_CASE105 case 106: goto BP_LABEL_N(106); 263 | #define __BP_CASE107 __BP_CASE106 case 107: goto BP_LABEL_N(107); 264 | #define __BP_CASE108 __BP_CASE107 case 108: goto BP_LABEL_N(108); 265 | #define __BP_CASE109 __BP_CASE108 case 109: goto BP_LABEL_N(109); 266 | #define __BP_CASE110 __BP_CASE109 case 110: goto BP_LABEL_N(110); 267 | #define __BP_CASE111 __BP_CASE110 case 111: goto BP_LABEL_N(111); 268 | #define __BP_CASE112 __BP_CASE111 case 112: goto BP_LABEL_N(112); 269 | #define __BP_CASE113 __BP_CASE112 case 113: goto BP_LABEL_N(113); 270 | #define __BP_CASE114 __BP_CASE113 case 114: goto BP_LABEL_N(114); 271 | #define __BP_CASE115 __BP_CASE114 case 115: goto BP_LABEL_N(115); 272 | #define __BP_CASE116 __BP_CASE115 case 116: goto BP_LABEL_N(116); 273 | #define __BP_CASE117 __BP_CASE116 case 117: goto BP_LABEL_N(117); 274 | #define __BP_CASE118 __BP_CASE117 case 118: goto BP_LABEL_N(118); 275 | #define __BP_CASE119 __BP_CASE118 case 119: goto BP_LABEL_N(119); 276 | #define __BP_CASE120 __BP_CASE119 case 120: goto BP_LABEL_N(120); 277 | #define __BP_CASE121 __BP_CASE120 case 121: goto BP_LABEL_N(121); 278 | #define __BP_CASE122 __BP_CASE121 case 122: goto BP_LABEL_N(122); 279 | #define __BP_CASE123 __BP_CASE122 case 123: goto BP_LABEL_N(123); 280 | #define __BP_CASE124 __BP_CASE123 case 124: goto BP_LABEL_N(124); 281 | #define __BP_CASE125 __BP_CASE124 case 125: goto BP_LABEL_N(125); 282 | #define __BP_CASE126 __BP_CASE125 case 126: goto BP_LABEL_N(126); 283 | #define __BP_CASE127 __BP_CASE126 case 127: goto BP_LABEL_N(127); 284 | #define __BP_CASE128 __BP_CASE127 case 128: goto BP_LABEL_N(128); 285 | #define __BP_CASE129 __BP_CASE128 case 129: goto BP_LABEL_N(129); 286 | #define __BP_CASE130 __BP_CASE129 case 130: goto BP_LABEL_N(130); 287 | #define __BP_CASE131 __BP_CASE130 case 131: goto BP_LABEL_N(131); 288 | #define __BP_CASE132 __BP_CASE131 case 132: goto BP_LABEL_N(132); 289 | #define __BP_CASE133 __BP_CASE132 case 133: goto BP_LABEL_N(133); 290 | #define __BP_CASE134 __BP_CASE133 case 134: goto BP_LABEL_N(134); 291 | #define __BP_CASE135 __BP_CASE134 case 135: goto BP_LABEL_N(135); 292 | #define __BP_CASE136 __BP_CASE135 case 136: goto BP_LABEL_N(136); 293 | #define __BP_CASE137 __BP_CASE136 case 137: goto BP_LABEL_N(137); 294 | #define __BP_CASE138 __BP_CASE137 case 138: goto BP_LABEL_N(138); 295 | #define __BP_CASE139 __BP_CASE138 case 139: goto BP_LABEL_N(139); 296 | #define __BP_CASE140 __BP_CASE139 case 140: goto BP_LABEL_N(140); 297 | #define __BP_CASE141 __BP_CASE140 case 141: goto BP_LABEL_N(141); 298 | #define __BP_CASE142 __BP_CASE141 case 142: goto BP_LABEL_N(142); 299 | #define __BP_CASE143 __BP_CASE142 case 143: goto BP_LABEL_N(143); 300 | #define __BP_CASE144 __BP_CASE143 case 144: goto BP_LABEL_N(144); 301 | #define __BP_CASE145 __BP_CASE144 case 145: goto BP_LABEL_N(145); 302 | #define __BP_CASE146 __BP_CASE145 case 146: goto BP_LABEL_N(146); 303 | #define __BP_CASE147 __BP_CASE146 case 147: goto BP_LABEL_N(147); 304 | #define __BP_CASE148 __BP_CASE147 case 148: goto BP_LABEL_N(148); 305 | #define __BP_CASE149 __BP_CASE148 case 149: goto BP_LABEL_N(149); 306 | #define __BP_CASE150 __BP_CASE149 case 150: goto BP_LABEL_N(150); 307 | #define __BP_CASE151 __BP_CASE150 case 151: goto BP_LABEL_N(151); 308 | #define __BP_CASE152 __BP_CASE151 case 152: goto BP_LABEL_N(152); 309 | #define __BP_CASE153 __BP_CASE152 case 153: goto BP_LABEL_N(153); 310 | #define __BP_CASE154 __BP_CASE153 case 154: goto BP_LABEL_N(154); 311 | #define __BP_CASE155 __BP_CASE154 case 155: goto BP_LABEL_N(155); 312 | #define __BP_CASE156 __BP_CASE155 case 156: goto BP_LABEL_N(156); 313 | #define __BP_CASE157 __BP_CASE156 case 157: goto BP_LABEL_N(157); 314 | #define __BP_CASE158 __BP_CASE157 case 158: goto BP_LABEL_N(158); 315 | #define __BP_CASE159 __BP_CASE158 case 159: goto BP_LABEL_N(159); 316 | #define __BP_CASE160 __BP_CASE159 case 160: goto BP_LABEL_N(160); 317 | #define __BP_CASE161 __BP_CASE160 case 161: goto BP_LABEL_N(161); 318 | #define __BP_CASE162 __BP_CASE161 case 162: goto BP_LABEL_N(162); 319 | #define __BP_CASE163 __BP_CASE162 case 163: goto BP_LABEL_N(163); 320 | #define __BP_CASE164 __BP_CASE163 case 164: goto BP_LABEL_N(164); 321 | #define __BP_CASE165 __BP_CASE164 case 165: goto BP_LABEL_N(165); 322 | #define __BP_CASE166 __BP_CASE165 case 166: goto BP_LABEL_N(166); 323 | #define __BP_CASE167 __BP_CASE166 case 167: goto BP_LABEL_N(167); 324 | #define __BP_CASE168 __BP_CASE167 case 168: goto BP_LABEL_N(168); 325 | #define __BP_CASE169 __BP_CASE168 case 169: goto BP_LABEL_N(169); 326 | #define __BP_CASE170 __BP_CASE169 case 170: goto BP_LABEL_N(170); 327 | #define __BP_CASE171 __BP_CASE170 case 171: goto BP_LABEL_N(171); 328 | #define __BP_CASE172 __BP_CASE171 case 172: goto BP_LABEL_N(172); 329 | #define __BP_CASE173 __BP_CASE172 case 173: goto BP_LABEL_N(173); 330 | #define __BP_CASE174 __BP_CASE173 case 174: goto BP_LABEL_N(174); 331 | #define __BP_CASE175 __BP_CASE174 case 175: goto BP_LABEL_N(175); 332 | #define __BP_CASE176 __BP_CASE175 case 176: goto BP_LABEL_N(176); 333 | #define __BP_CASE177 __BP_CASE176 case 177: goto BP_LABEL_N(177); 334 | #define __BP_CASE178 __BP_CASE177 case 178: goto BP_LABEL_N(178); 335 | #define __BP_CASE179 __BP_CASE178 case 179: goto BP_LABEL_N(179); 336 | #define __BP_CASE180 __BP_CASE179 case 180: goto BP_LABEL_N(180); 337 | #define __BP_CASE181 __BP_CASE180 case 181: goto BP_LABEL_N(181); 338 | #define __BP_CASE182 __BP_CASE181 case 182: goto BP_LABEL_N(182); 339 | #define __BP_CASE183 __BP_CASE182 case 183: goto BP_LABEL_N(183); 340 | #define __BP_CASE184 __BP_CASE183 case 184: goto BP_LABEL_N(184); 341 | #define __BP_CASE185 __BP_CASE184 case 185: goto BP_LABEL_N(185); 342 | #define __BP_CASE186 __BP_CASE185 case 186: goto BP_LABEL_N(186); 343 | #define __BP_CASE187 __BP_CASE186 case 187: goto BP_LABEL_N(187); 344 | #define __BP_CASE188 __BP_CASE187 case 188: goto BP_LABEL_N(188); 345 | #define __BP_CASE189 __BP_CASE188 case 189: goto BP_LABEL_N(189); 346 | #define __BP_CASE190 __BP_CASE189 case 190: goto BP_LABEL_N(190); 347 | #define __BP_CASE191 __BP_CASE190 case 191: goto BP_LABEL_N(191); 348 | #define __BP_CASE192 __BP_CASE191 case 192: goto BP_LABEL_N(192); 349 | #define __BP_CASE193 __BP_CASE192 case 193: goto BP_LABEL_N(193); 350 | #define __BP_CASE194 __BP_CASE193 case 194: goto BP_LABEL_N(194); 351 | #define __BP_CASE195 __BP_CASE194 case 195: goto BP_LABEL_N(195); 352 | #define __BP_CASE196 __BP_CASE195 case 196: goto BP_LABEL_N(196); 353 | #define __BP_CASE197 __BP_CASE196 case 197: goto BP_LABEL_N(197); 354 | #define __BP_CASE198 __BP_CASE197 case 198: goto BP_LABEL_N(198); 355 | #define __BP_CASE199 __BP_CASE198 case 199: goto BP_LABEL_N(199); 356 | #define __BP_CASE200 __BP_CASE199 case 200: goto BP_LABEL_N(200); 357 | #define __BP_CASE201 __BP_CASE200 case 201: goto BP_LABEL_N(201); 358 | #define __BP_CASE202 __BP_CASE201 case 202: goto BP_LABEL_N(202); 359 | #define __BP_CASE203 __BP_CASE202 case 203: goto BP_LABEL_N(203); 360 | #define __BP_CASE204 __BP_CASE203 case 204: goto BP_LABEL_N(204); 361 | #define __BP_CASE205 __BP_CASE204 case 205: goto BP_LABEL_N(205); 362 | #define __BP_CASE206 __BP_CASE205 case 206: goto BP_LABEL_N(206); 363 | #define __BP_CASE207 __BP_CASE206 case 207: goto BP_LABEL_N(207); 364 | #define __BP_CASE208 __BP_CASE207 case 208: goto BP_LABEL_N(208); 365 | #define __BP_CASE209 __BP_CASE208 case 209: goto BP_LABEL_N(209); 366 | #define __BP_CASE210 __BP_CASE209 case 210: goto BP_LABEL_N(210); 367 | #define __BP_CASE211 __BP_CASE210 case 211: goto BP_LABEL_N(211); 368 | #define __BP_CASE212 __BP_CASE211 case 212: goto BP_LABEL_N(212); 369 | #define __BP_CASE213 __BP_CASE212 case 213: goto BP_LABEL_N(213); 370 | #define __BP_CASE214 __BP_CASE213 case 214: goto BP_LABEL_N(214); 371 | #define __BP_CASE215 __BP_CASE214 case 215: goto BP_LABEL_N(215); 372 | #define __BP_CASE216 __BP_CASE215 case 216: goto BP_LABEL_N(216); 373 | #define __BP_CASE217 __BP_CASE216 case 217: goto BP_LABEL_N(217); 374 | #define __BP_CASE218 __BP_CASE217 case 218: goto BP_LABEL_N(218); 375 | #define __BP_CASE219 __BP_CASE218 case 219: goto BP_LABEL_N(219); 376 | #define __BP_CASE220 __BP_CASE219 case 220: goto BP_LABEL_N(220); 377 | #define __BP_CASE221 __BP_CASE220 case 221: goto BP_LABEL_N(221); 378 | #define __BP_CASE222 __BP_CASE221 case 222: goto BP_LABEL_N(222); 379 | #define __BP_CASE223 __BP_CASE222 case 223: goto BP_LABEL_N(223); 380 | #define __BP_CASE224 __BP_CASE223 case 224: goto BP_LABEL_N(224); 381 | #define __BP_CASE225 __BP_CASE224 case 225: goto BP_LABEL_N(225); 382 | #define __BP_CASE226 __BP_CASE225 case 226: goto BP_LABEL_N(226); 383 | #define __BP_CASE227 __BP_CASE226 case 227: goto BP_LABEL_N(227); 384 | #define __BP_CASE228 __BP_CASE227 case 228: goto BP_LABEL_N(228); 385 | #define __BP_CASE229 __BP_CASE228 case 229: goto BP_LABEL_N(229); 386 | #define __BP_CASE230 __BP_CASE229 case 230: goto BP_LABEL_N(230); 387 | #define __BP_CASE231 __BP_CASE230 case 231: goto BP_LABEL_N(231); 388 | #define __BP_CASE232 __BP_CASE231 case 232: goto BP_LABEL_N(232); 389 | #define __BP_CASE233 __BP_CASE232 case 233: goto BP_LABEL_N(233); 390 | #define __BP_CASE234 __BP_CASE233 case 234: goto BP_LABEL_N(234); 391 | #define __BP_CASE235 __BP_CASE234 case 235: goto BP_LABEL_N(235); 392 | #define __BP_CASE236 __BP_CASE235 case 236: goto BP_LABEL_N(236); 393 | #define __BP_CASE237 __BP_CASE236 case 237: goto BP_LABEL_N(237); 394 | #define __BP_CASE238 __BP_CASE237 case 238: goto BP_LABEL_N(238); 395 | #define __BP_CASE239 __BP_CASE238 case 239: goto BP_LABEL_N(239); 396 | #define __BP_CASE240 __BP_CASE239 case 240: goto BP_LABEL_N(240); 397 | #define __BP_CASE241 __BP_CASE240 case 241: goto BP_LABEL_N(241); 398 | #define __BP_CASE242 __BP_CASE241 case 242: goto BP_LABEL_N(242); 399 | #define __BP_CASE243 __BP_CASE242 case 243: goto BP_LABEL_N(243); 400 | #define __BP_CASE244 __BP_CASE243 case 244: goto BP_LABEL_N(244); 401 | #define __BP_CASE245 __BP_CASE244 case 245: goto BP_LABEL_N(245); 402 | #define __BP_CASE246 __BP_CASE245 case 246: goto BP_LABEL_N(246); 403 | #define __BP_CASE247 __BP_CASE246 case 247: goto BP_LABEL_N(247); 404 | #define __BP_CASE248 __BP_CASE247 case 248: goto BP_LABEL_N(248); 405 | #define __BP_CASE249 __BP_CASE248 case 249: goto BP_LABEL_N(249); 406 | #define __BP_CASE250 __BP_CASE249 case 250: goto BP_LABEL_N(250); 407 | #define __BP_CASE251 __BP_CASE250 case 251: goto BP_LABEL_N(251); 408 | #define __BP_CASE252 __BP_CASE251 case 252: goto BP_LABEL_N(252); 409 | #define __BP_CASE253 __BP_CASE252 case 253: goto BP_LABEL_N(253); 410 | #define __BP_CASE254 __BP_CASE253 case 254: goto BP_LABEL_N(254); 411 | #define __BP_CASE255 __BP_CASE254 case 255: goto BP_LABEL_N(255); 412 | 413 | /* then define a __BP_CAT_connection macro for use by __BP_CASEN */ 414 | /* 再定义一个__BP_CAT_连接宏,供__BP_CASEN使用 */ 415 | #define __BP_CAT_(x, y) __BP_CAT_1(x, y) 416 | #define __BP_CAT_1(x, y) x##y 417 | 418 | /* because __BP_CASE contains the __BP_CAT macro, 419 | * you cannot use the __BP_CAT macro again, 420 | * so use the __BP_CAT_ macro */ 421 | /* 由于__BP_CASE中包含了__BP_CAT宏, 422 | * 因此不可再次使用__BP_CAT宏, 423 | * 故使用__BP_CAT_宏 */ 424 | #define __BP_CASEN(bp_nums) __BP_CAT_(__BP_CASE, bp_nums) 425 | 426 | 427 | /********************************************************* 428 | *@brief: 429 | ***start a bp coroutine 430 | * 431 | *@contract: 432 | ***1. "bp_nums" must be a pure number, or a macro that is expanded to be a pure number 433 | ***2. "bp_nums" indicates the number of breakpoints contained between bp_begin() and bp_end() 434 | ***3. the breakpoint number between bp_begin() and bp_end() is continuous from 1 to n, 435 | *** and must not be missed or redundant. 436 | * 437 | *@parameter: 438 | *[bp_nums]: indicates the number of breakpoints contained between bp_begin() and bp_end() 439 | *[bp]: variable(1 byte) for recording the current breakpoint position, the life cycle is global 440 | *********************************************************/ 441 | /********************************************************* 442 | *@简要: 443 | ***开始一个bp协程 444 | * 445 | *@约定: 446 | ***1、bp_nums必须是纯数字,或者展开后为纯数字的宏 447 | ***2、bp_nums表示从bp_begin()到bp_end()之间包含的断点个数 448 | ***3、bp_begin()到bp_end()之间的断点号从1到n连续,不可遗漏与多余 449 | * 450 | *@参数: 451 | *[bp_nums]:表示bp_begin()到bp_end()之间包含的断点个数 452 | *[bp]:用于记录当前断点位置的生命周期为全局的变量(一个字节) 453 | **********************************************************/ 454 | #define bp_begin(bp_nums, bp) __BP_HEADER(bp) __BP_CASEN(bp_nums) __BP_TAIL 455 | 456 | 457 | /********************************************************* 458 | *@brief: 459 | ***together with bp_begin(), constitutes the scope of the coroutine 460 | * 461 | *@parameter: 462 | *[bp]: variable(1 byte) for recording the current breakpoint position, the life cycle is global 463 | *********************************************************/ 464 | /********************************************************* 465 | *@简要: 466 | ***与bp_begin()组成协程的作用域 467 | * 468 | *@参数: 469 | *[bp]:用于记录当前断点位置的生命周期为全局的变量(一个字节) 470 | **********************************************************/ 471 | #define bp_end(bp) \ 472 | do { BP_LABEL_END: (bp) = BP_INIT_VAL; } while (0) 473 | 474 | 475 | /************************************************************ 476 | *@brief: 477 | ***record the breakpoint number in the bp variable 478 | * 479 | *@parameter: 480 | *[bp_num]: recorded breakpoint number 481 | *[bp]: variable(1 byte) for recording the current breakpoint position, the life cycle is global 482 | *************************************************************/ 483 | /************************************************************ 484 | *@简介: 485 | ***将断点号记录在bp变量之中 486 | * 487 | *@参数: 488 | *[bp_num]:记录的断点号 489 | *[bp]:用于记录当前断点位置的生命周期为全局的变量(一个字节) 490 | *************************************************************/ 491 | #define bp_set(bp_num, bp) ((int)((bp) = (bp_num))) 492 | 493 | 494 | /************************************************************ 495 | *@brief: 496 | ***create a recovery location with a breakpoint of bp_num, 497 | ***and bp_begin() will jump to the appropriate recovery location 498 | ***based on the breakpoint number in the bp variable. 499 | * 500 | *@contract: 501 | ***1. create a recovery location with a different bp_num each time 502 | ***2. the breakpoint number between bp_begin() and bp_end() is continuous from 1 to n, 503 | *** and must not be missed or redundant. 504 | ***3. "bp_nums" must be a pure number, or a macro that is expanded to be a pure number 505 | * 506 | *@parameter: 507 | *[bp_num]: corresponding breakpoint number 508 | *************************************************************/ 509 | /************************************************************ 510 | *@简介: 511 | ***创建一个断点号为bp_num的恢复位置,bp_begin()会根据bp变量中的断点号 512 | ***跳转到相应的恢复位置。 513 | * 514 | *@约定: 515 | ***1、每次都使用不同的bp_num创建恢复位置 516 | ***2、bp_begin()到bp_end()之间的断点号从1到n连续,不可遗漏与多余 517 | ***3、bp_nums必须是纯数字,或者展开后为纯数字的宏 518 | * 519 | *@参数: 520 | *[bp_num]:对应的断点号 521 | *************************************************************/ 522 | #define bp_restore_point(bp_num) BP_LABEL_N(bp_num) 523 | 524 | 525 | /************************************************************************* 526 | * BP initialization 527 | * BP初始化 528 | ************************************************************************* 529 | */ 530 | #define BP_INIT_VAL 0 531 | #define bp_init(bp) ((bp) = BP_INIT_VAL) 532 | 533 | 534 | /********************************************************* 535 | *@description: 536 | ***BP yield series 537 | * 538 | *@note: 539 | ***the bp_yield family of functions consists of bp_set and bp_restore_point, 540 | ***so you need to follow the usage contract of bp_restore_point. 541 | ***as follows: 542 | ***1. "bp_nums" must be a pure number, or a macro that is expanded to be a pure number 543 | ***2. the breakpoint number between bp_begin() and bp_end() is continuous from 1 to n, 544 | *** and must not be missed or redundant. 545 | ********************************************************* 546 | *@说明: 547 | ***BP yield系列函数 548 | * 549 | *@注意: 550 | ***bp_yield系列函数由bp_set与bp_restore_point组成,因此需要 551 | ***遵守bp_restore_point的使用约定。 552 | ***如下: 553 | ***1、bp_nums必须是纯数字,或者展开后为纯数字的宏 554 | ***2、bp_begin()到bp_end()之间的断点号从1到n连续,不可遗漏与多余 555 | *********************************************************/ 556 | 557 | /* Active return, followed by a statement or value, 558 | * and restore the current execution position in the next call */ 559 | /* 主动返回,后面可以跟一条语句或值,并在下次调用恢复当前执行位置 */ 560 | #define bp_yield(bp_num, bp) \ 561 | if (0) \ 562 | { \ 563 | bp_restore_point(bp_num):; \ 564 | } \ 565 | else while (bp_set(bp_num, bp)) \ 566 | return 567 | 568 | /************************************************************************* 569 | * BP other series 570 | * BP 其他系列 571 | ************************************************************************* 572 | */ 573 | 574 | /* jump out of the BP_BEGIN to BP_END statement */ 575 | /* 跳出BP_BEGIN到BP_END包含的语句之外 */ 576 | #define bp_break \ 577 | do {goto BP_LABEL_END; } while (0) 578 | 579 | /* re-execution after BP_BEGIN */ 580 | /* 从BP_BEGIN之后重新执行 */ 581 | #define bp_continue \ 582 | do { goto BP_LABEL_START; } while (0) 583 | 584 | /* exit BP_BEGIN-BP_END statement block, 585 | * the next call will be re-executed */ 586 | /* 退出BP_BEGIN-BP_END语句块,下次调用将重新执行 */ 587 | #define bp_exit(bp) \ 588 | while (((bp) = BP_INIT_VAL) || 1) return 589 | 590 | /* return directly without 591 | * modifying the breakpoint location */ 592 | /* 直接返回,不修改断点位置 */ 593 | #define bp_ret return 594 | 595 | /************************************************************ 596 | * define a bpd pointer to use BPD series macros, 597 | * omit bp parameter 598 | * usage: 599 | * 600 | * unsigned char *bpd = &ctx->bp; 601 | * 602 | * bpd_begin(1) 603 | * 604 | * bpd_yield(1); 605 | * 606 | * bpd_end(); 607 | * 608 | ************************************************************/ 609 | /************************************************************ 610 | * 定义一个bpd指针,可使用BPD系列宏,省略bp参数 611 | * 例: 612 | * 613 | * unsigned char *bpd = &ctx->bp; 614 | * 615 | * bpd_begin(1) 616 | * 617 | * bpd_yield(1); 618 | * 619 | * bpd_end(); 620 | * 621 | ************************************************************/ 622 | 623 | /* default bpd as the bp parameter 624 | * of the bp series macro */ 625 | /* 将bpd默认作为bp系列宏的bp参数 */ 626 | #define BP_DEFAULT *bpd 627 | 628 | #define BPD_INIT_VAL 0 629 | 630 | #define bpd_init(bp) ((BP_DEFAULT) = BP_INIT_VAL) 631 | 632 | #define bpd_restore_point(point) bp_restore_point(point) 633 | 634 | #define bpd_begin(bp_nums) bp_begin(bp_nums, (BP_DEFAULT)) 635 | 636 | #define bpd_end() bp_end((BP_DEFAULT)) 637 | 638 | #define bpd_set(bp_num) bp_set(bp_num, (BP_DEFAULT)) 639 | 640 | #define bpd_yield(bp_num) bp_yield(bp_num, (BP_DEFAULT)) 641 | 642 | #define bpd_break bp_break 643 | 644 | #define bpd_continue bp_continue 645 | 646 | #define bpd_exit() bp_exit((BP_DEFAULT)) 647 | 648 | #define bpd_ret bp_ret 649 | 650 | #endif /* __BP_H__ */ 651 | -------------------------------------------------------------------------------- /demo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 xiaoliang<1296283984@qq.com>. 3 | */ 4 | 5 | #include "bp.h" 6 | #include 7 | #include 8 | 9 | typedef struct 10 | { 11 | /* resource */ 12 | short res; 13 | 14 | /* consumer coroutine breakpoint */ 15 | unsigned char consumer_bp; 16 | 17 | /* produce coroutine breakpoint */ 18 | unsigned char producer_bp; 19 | } res_t; 20 | 21 | #define TRUE 1 22 | #define FALSE (!TRUE) 23 | 24 | int consumer(res_t *res) 25 | { 26 | /* bpd coroutine default breakpoint pointer */ 27 | unsigned char *bpd = &res->consumer_bp; 28 | 29 | /* coroutine begin */ 30 | bpd_begin(2); 31 | 32 | while (1) 33 | { 34 | /* wait number of resource > 0 */ 35 | while (res->res <= 0) 36 | { 37 | bpd_yield(1) FALSE; 38 | } 39 | 40 | /* consume */ 41 | res->res--; 42 | printf("consume a resource, number of res:%d\n", res->res); 43 | 44 | /* wait next consume */ 45 | bpd_yield(2) TRUE; 46 | } 47 | 48 | /* coroutine end */ 49 | bpd_end(); 50 | } 51 | 52 | int producer(res_t *res) 53 | { 54 | /* bpd coroutine default breakpoint pointer */ 55 | unsigned char *bpd = &res->producer_bp; 56 | 57 | /* coroutine begin */ 58 | bpd_begin(2); 59 | 60 | while (1) 61 | { 62 | /* wait number of resource < 30 */ 63 | while (res->res >= 30) 64 | { 65 | bpd_yield(1) FALSE; 66 | } 67 | 68 | /* produce */ 69 | res->res++; 70 | printf("produce a resource, number of res:%d\n", res->res); 71 | 72 | /* wait next produce */ 73 | bpd_yield(2) TRUE; 74 | } 75 | 76 | /* coroutine end */ 77 | bpd_end(); 78 | } 79 | 80 | int main() 81 | { 82 | res_t res = {0, BP_INIT_VAL, BP_INIT_VAL}; 83 | int nrand; 84 | 85 | /* initialize random */ 86 | srand(122); 87 | 88 | /* randomly produce and consume */ 89 | while (1) 90 | { 91 | nrand = rand() % 16; 92 | while (nrand--) 93 | { 94 | if (consumer(&res) == FALSE) 95 | break; 96 | } 97 | 98 | nrand = rand() % 16; 99 | while (nrand--) 100 | { 101 | if (producer(&res) == FALSE) 102 | break; 103 | } 104 | } 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoliang314/lw_coroutine/af044d3da228ceb1b6bb8e9170ae6a7bd96adea2/demo.gif --------------------------------------------------------------------------------