C语言小技巧:带扫尾工作的宏
前两天为了在C下编写一个类似Erlang式消息传递的框架,需要定义一个receive宏,使得coroutine处理函数的编写可以类似这样:
int foo() { ... receive(msg) { // Deal with the message } ... receive(msg) { // Deal with another message } ... }
因为foo()函数以coroutine方式执行,所以消息的及时释放就显得尤为重要了,receive()之后紧接的代码块就是这个消息的生存周期,完成之后需要立即对消息进行释放。这就对receive宏的编写提出了一个特别的要求:包含扫尾工作。
最后定义出来的宏是这样的:
#define receive(msg) if (0); for (msg = co_recvmsg(); msg; co_freemsg(msg), msg = NULL)
co_recvmsg()是一个阻塞式的消息接收函数,co_freemsg()就是那个负责释放消息的接口。开头的“if 0”则是为了避免当在同一层次中两次调用receive时使用相同的参数名可能导致的VC下编译错误(GCC没有这个问题)。
如果开启了优化选项,编译器将消除上述宏展开后的循环体,最终优化后的代码实际等效于:
// Source: receive(msg) { ... } { msg = co_recvmsg(); if (msg) { ... } co_freemsg(msg); msg = NULL; }
Written on July 27, 2008