徐锦洪 发表于 2024-8-19 06:59:49

C基础——用标签实现队列使命调用,即PostgreSQL内核函数调用时ExecInterpE

=================================版权声明=================================
版权声明:原创文章 禁止转载 

请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我
勿用于学术性引用。
勿用于贸易出版、贸易印刷、贸易引用以及其他贸易用途。                   
 
本文不定期修正美满。
本文链接:https://www.cnblogs.com/wlsandwho/p/18350973
羞耻墙:http://www.cnblogs.com/wlsandwho/p/4206472.html
=======================================================================
这几年在搞数据库。近来离职了,想在青岛找工作。
闲着没事,写点东西。
=======================================================================
由于工作的内容收到保密协议的影响,只能写点零散的小东西。
=======================================================================
看过PG代码的朋友都知道,PG执行函数的时候,在内核有一块奇怪的代码,函数名叫做ExecInterpExpr,文件名叫做execExprInterp.c
这个函数里面有一个EEO_SWITCH和很多EEO_CASE,然后调试起来很奇怪。
=======================================================================
实在,这个是一些奇技淫巧而已。
为避免依次调用很多功能函数、一套参数在各个函数间传递
PG让各个功能都在一个大函数里实现,通过在差别的功能块间跳转,实现雷同的结果。
=======================================================================
因此,这个现实上是goto lable的花哨用法。固然PG9时代,这块代码不是这个样子的。
=======================================================================
我这里给大家写一个好理解的简化版本。
要注意的是,获取lable地址的做法,gcc支持,MSVC不支持。
1 //gcc -g -o main demo_runlable.c -std=c992 #include   3   4 #define WORK_ARRAY_LEN 325 int gWorkIndex=0;6 static void* gWorkArray={};7   8 #define MY_SWITCH()   9 #define MY_CASE(val) MYLABE_##val 10 #define MY_OP_FROM_OPNUM(opnum) ((void*)gDispatchTable)11 #define MY_DISPATCH()do{\ 12                         gWorkIndex=0;\ 13                         goto *(gWorkArray);\ 14                     }while(0) 15 #define MY_NEXT()   do{\ 16                         gWorkIndex++;\ 17                         goto *(gWorkArray);\ 18                     }while(0) 1920 enum OPNUM 21 { 22   OPNUM_0=0, 23   OPNUM_1, 24   OPNUM_2, 25   OPNUM_3, 26   OPNUM_4, 27   OPNUM_5, 28   OPNUM_END 29 }; 3031 static void** gDispatchTable=NULL; 32 static void* MyRunning(int run) 33 { 34   static void* mydispatchtable[] =35   { 36         && MY_CASE(OPNUM_0), 37         && MY_CASE(OPNUM_1), 38         && MY_CASE(OPNUM_2) , 39         && MY_CASE(OPNUM_3), 40         && MY_CASE(OPNUM_4), 41         && MY_CASE(OPNUM_5), 42         && MY_CASE(OPNUM_END) 43   }; 4445   if(run != 0) 46   { 47         MY_DISPATCH(); 48   } 49   else 50   { 51         return mydispatchtable; 52   } 5354   MY_SWITCH() 55   { 56         MY_CASE(OPNUM_0) : 57         { 58             printf("0"); 59             MY_NEXT(); 60         } 6162         MY_CASE(OPNUM_1) : 63         { 64             printf("1"); 65             MY_NEXT(); 66         } 6768         MY_CASE(OPNUM_2) : 69         { 70             printf("2"); 71             MY_NEXT(); 72         } 7374         MY_CASE(OPNUM_3) : 75         { 76             printf("3"); 77                MY_NEXT(); 78         } 7980         MY_CASE(OPNUM_4) : 81         { 82             printf("4"); 83             MY_NEXT(); 84         } 8586         MY_CASE(OPNUM_5) : 87         { 88             printf("5"); 89             MY_NEXT(); 90         } 9192         MY_CASE(OPNUM_END) : 93         { 94             printf("\n"); 95             goto out; 96         } 97   } 98 out: 99   return NULL;100 }101 102 103 void Test1()104 {105   //init106   gDispatchTable=MyRunning(0);107 108   //reset109   for(int i=0;i
页: [1]
查看完整版本: C基础——用标签实现队列使命调用,即PostgreSQL内核函数调用时ExecInterpE