您的当前位置:首页正文

C基础——用标签实现队列任务调用,即PostgreSQL内核函数调用时ExecInterpExpr的原理解析

2024-10-17 来源:个人技术集锦

================================= 版权声明 =================================

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

请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我

勿用于学术性引用。

勿用于商业出版、商业印刷、商业引用以及其他商业用途。

本文不定期修正完善。

本文链接:https://www.cnblogs.com/wlsandwho/p/18350973

耻辱墙:

=======================================================================

这几年在搞数据库。最近离职了,想在青岛找工作。

闲着没事,写点东西。

=======================================================================

由于工作的内容收到保密协议的影响,只能写点零散的小东西。

=======================================================================

看过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=c99  2 #include <stdio.h>  3   4 #define WORK_ARRAY_LEN 32  5 int gWorkIndex=0;  6 static void* gWorkArray[WORK_ARRAY_LEN]={};  7   8 #define MY_SWITCH()   9 #define MY_CASE(val) MYLABE_##val 10 #define MY_OP_FROM_OPNUM(opnum) ((void*)gDispatchTable[opnum])  11 #define MY_DISPATCH()  do{\ 12                         gWorkIndex=0;\ 13                         goto *(gWorkArray[gWorkIndex]);\ 14                     }while(0) 15 #define MY_NEXT()   do{\ 16                         gWorkIndex++;\ 17                         goto *(gWorkArray[gWorkIndex]);\ 18                     }while(0) 19  20 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 }; 30  31 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     }; 44  45     if(run != 0) 46     { 47         MY_DISPATCH(); 48     } 49     else 50     { 51         return mydispatchtable; 52     } 53  54     MY_SWITCH() 55     { 56         MY_CASE(OPNUM_0) : 57         { 58             printf("0"); 59             MY_NEXT(); 60         } 61  62         MY_CASE(OPNUM_1) : 63         { 64             printf("1"); 65             MY_NEXT(); 66         } 67  68         MY_CASE(OPNUM_2) : 69         { 70             printf("2"); 71             MY_NEXT(); 72         } 73  74         MY_CASE(OPNUM_3) : 75         { 76             printf("3"); 77                MY_NEXT(); 78         } 79  80         MY_CASE(OPNUM_4) : 81         { 82             printf("4"); 83             MY_NEXT(); 84         } 85  86         MY_CASE(OPNUM_5) : 87         { 88             printf("5"); 89             MY_NEXT(); 90         } 91  92         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<WORK_ARRAY_LEN;i++)110     {111         gWorkArray[i]= MY_OP_FROM_OPNUM(OPNUM_END);112     }113 114     //set work115     gWorkArray[0] = MY_OP_FROM_OPNUM(OPNUM_5);116     gWorkArray[1] = MY_OP_FROM_OPNUM(OPNUM_2);117     gWorkArray[2] = MY_OP_FROM_OPNUM(OPNUM_0);118     gWorkArray[3] = MY_OP_FROM_OPNUM(OPNUM_1);119     gWorkArray[4] = MY_OP_FROM_OPNUM(OPNUM_3);120     gWorkArray[5] = MY_OP_FROM_OPNUM(OPNUM_1);121     gWorkArray[6] = MY_OP_FROM_OPNUM(OPNUM_4);122 123     //run124     MyRunning(1);125 }126 127 int main()128 {129     Test1();130     return 0;131 }

效果如下。

1 [postgres@pg1 testDemo]$ gcc -o main demo_runlable.c -std=c99 -g2 [postgres@pg1 testDemo]$ ./main 3 52013144 [postgres@pg1 testDemo]$ 

显示全文