如何检查函数是否正在回调自身
How to check if a function is calling back to itself
假设我们在库中有一个 C 函数 funA,在 funA 内部它会调用一些其他函数 funB、funC 等。 funB 和 funC 可能会回调 funA。所以问题是:
是否可以在 funA 内部检测到这种情况,例如:
void funA(void) {
if (...) {
// Calling back to funA
}
}
结论
- 在单线程环境中,static/global 变量可以工作。
- 在多线程环境中,必须依赖 TLS 支持。
- 还没有任何答案可以仅通过语言 (C) 级别的技巧来实现此目的
如果是单次调用,可以在调用一次这个函数的时候设置一个global/static标志,在开始的时候检查一下。或者为了取消单次调用的限制,您可以在函数返回之前重置此标志。
类似的东西:
void funA(void) {
static bool used = false;
if (used)
{
printf("It is used!\n");
}
used = true;
// .... Do stuff here, including possible recursion
used = false;
}
注意 - 这不适用于多线程 - 此函数不可重入..
这可以通过静态标志来完成。
调用该函数时,如果未设置标志,则设置它并继续,否则立即return。然后在函数结束时,清除标志以便再次输入。
void funcA(void)
{
static int callback = 0;
if (callback) return;
callback = 1;
...
callback = 0;
}
如果这需要在多线程中单独工作,您可以将变量声明为 _Thread_local
而不是 static
。
通过间接级别,您甚至可以计算函数被调用的次数:
void func( int count )
{
printf( "Count is %d\n", count );
if ( ... ) // no longer want to recurse...
{
return;
}
func( count + 1 );
}
// wrap the actual recursive call to hide the parameter
void funA()
{
func( 0 );
}
这样,它是完全线程安全的。如果您不想传递包装函数或参数,则可以使用 thread-specific storage.
也许您可以通过另一种方法识别来电者:
void func_a(void *ptr);
void func_b(void);
void func_c(void);
void func_a(void *caller)
{
if(caller == func_a)
{
printf("called from func_a\n");
return;
}
if(caller == func_b)
{
printf("called from func_b\n");
return;
}
if(caller == func_c)
{
printf("called from func_c\n");
return;
}
if(caller == NULL)
{
printf("called from somewhere elese - going to call myself\n");
func_a(func_a);
}
}
void func_b()
{
func_a(func_b);
}
void func_c()
{
func_a(func_c);
}
int main()
{
func_b();
func_c();
func_a(NULL);
return 0;
}
假设我们在库中有一个 C 函数 funA,在 funA 内部它会调用一些其他函数 funB、funC 等。 funB 和 funC 可能会回调 funA。所以问题是: 是否可以在 funA 内部检测到这种情况,例如:
void funA(void) {
if (...) {
// Calling back to funA
}
}
结论
- 在单线程环境中,static/global 变量可以工作。
- 在多线程环境中,必须依赖 TLS 支持。
- 还没有任何答案可以仅通过语言 (C) 级别的技巧来实现此目的
如果是单次调用,可以在调用一次这个函数的时候设置一个global/static标志,在开始的时候检查一下。或者为了取消单次调用的限制,您可以在函数返回之前重置此标志。 类似的东西:
void funA(void) {
static bool used = false;
if (used)
{
printf("It is used!\n");
}
used = true;
// .... Do stuff here, including possible recursion
used = false;
}
注意 - 这不适用于多线程 - 此函数不可重入..
这可以通过静态标志来完成。
调用该函数时,如果未设置标志,则设置它并继续,否则立即return。然后在函数结束时,清除标志以便再次输入。
void funcA(void)
{
static int callback = 0;
if (callback) return;
callback = 1;
...
callback = 0;
}
如果这需要在多线程中单独工作,您可以将变量声明为 _Thread_local
而不是 static
。
通过间接级别,您甚至可以计算函数被调用的次数:
void func( int count )
{
printf( "Count is %d\n", count );
if ( ... ) // no longer want to recurse...
{
return;
}
func( count + 1 );
}
// wrap the actual recursive call to hide the parameter
void funA()
{
func( 0 );
}
这样,它是完全线程安全的。如果您不想传递包装函数或参数,则可以使用 thread-specific storage.
也许您可以通过另一种方法识别来电者:
void func_a(void *ptr);
void func_b(void);
void func_c(void);
void func_a(void *caller)
{
if(caller == func_a)
{
printf("called from func_a\n");
return;
}
if(caller == func_b)
{
printf("called from func_b\n");
return;
}
if(caller == func_c)
{
printf("called from func_c\n");
return;
}
if(caller == NULL)
{
printf("called from somewhere elese - going to call myself\n");
func_a(func_a);
}
}
void func_b()
{
func_a(func_b);
}
void func_c()
{
func_a(func_c);
}
int main()
{
func_b();
func_c();
func_a(NULL);
return 0;
}