int (*iter)(void *data, void *arg)
是函数指针。当您拨打fifo_iter
时,您会在第二个参数中传递一个回调函数。此功能必须有一个签名,如:
int my_callback(void* data, void* arg)
此功能将被要求在fifo_t
每一个项目。它将通过data
参数中的fn_data
成员。无论您通过的是arg
还是fifo_iter
,都将以arg
的参数传递给iter
。这是将通用“上下文”信息传递给回调的常用方法,而不必诉诸丑陋的,线程不安全的全局变量。
所以你可以使用它像这样:
int my_callback(void* data, void* arg) {
printf("my_callback(%p, %p)\n", data, arg);
return 0; // always continue
}
void test(void) {
fifo_t myfifo; // Needs initialized and populated...
fifo_iter(&myfifo, my_callback, NULL);
}
此外,我们看到它使用的iter
返回值以特殊的方式。首先,如果iter
曾经返回负值,则迭代立即停止,并且fifo_iter
返回-1。这可能是一个“早期失败”。否则,它将(正)返回值累加到ret
中,然后返回该值。
展开我的示例。这假设fifo fn_data
成员指向字符串。这将计算FIFO中所有字符串中大写和小写字母的总数,并返回所有字符串的总长度。
// The context that we'll maintain during the iteration
struct my_context {
int caps;
int lowers;
};
// The callback function, called for every string in the FIFO.
int my_callback(void* data, void* arg) {
const char* str = data; // Node data is a string
struct my_context *ctx = arg; // Arg is my context
// If any string in the FIFO has a !, abort immediately.
if (strchr(str, '!'))
return -1;
// Update the context to include the counts for this string
ctx->caps += count_capital_letters(str);
ctx->lowers += count_lowercase_letters(str);
// fifo_iter will accumulate this length
return strlen(str);
}
// Test driver function
void test(void) {
fifo_t myfifo;
struct my_context ctx;
int total;
// Assuming these functions exist:
fifo_init(&myfifo);
fifo_append(&myfifo, "Stack");
fifo_append(&myfifo, "Overflow");
// Initialize the context
ctx.caps = 0;
ctx.lowers = 0;
// Iterate over myfifo, passing it a pointer to the context
total = fifo_iter(&myfifo, my_callback, &ctx);
if (total < 0) {
// Any string had a '!'
printf("Iteration failed!\n");
return;
}
printf("total=%d caps=%d lowers=%d \n", total, ctx.caps, ctx.lowers);
}
如果你通过Linux内核源代码挑剔,你会看到这个构造遍布整个地方。
对于像我们这样简单的FIFO,看起来似乎不值得。但是,当你处理更复杂的数据结构如散列表和RCU列表时,将迭代逻辑保持在一个地方更合理,并且可以使用回调来以任何需要的方式处理数据。
你好。我试图将int变量添加到此fifo。但我只能看到相同的var(这是最后一个var)for(int i = 0; i <4; i ++)int * k = malloc(sizeof(int)); * k = rand(); fifo_add(ff,k); free(k); } fifo_iter(ff,my_callback,NULL); – Max
@garrydvaraza如果您有新问题,请提出新问题。评论是不正确的地方。 –