Vin*_*vic 6 c encapsulation reentrancy
假设我正在构建一个库,以便在C中使用quuxes.
Quuxes需要两个状态变量成功sporked:
static int quux_state;
static char* quux_address;
/* function to spork quuxes found in a file,
reads a line from the file each time it's called. */
void spork_quux(FILE*);
Run Code Online (Sandbox Code Playgroud)
如果我将这些数据存储为全局变量,那么只有一个客户端能够一次启动quuxes,否则状态变量将被第二个调用者破坏,并可能发生灾难.
问题是在C中设计可重入库的最佳方法是什么?
我接受了以下案件,但没有令人满意的结论.
在下面的例子中,问题是如何将客户关联到每个州?
/* library handles all state data allocation */
static int* quux_state;
static char** quux_address;
Run Code Online (Sandbox Code Playgroud)
在下面的例子中,客户端能够搞乱状态,非常不受欢迎
/* let each client store state */
typedef struct { int state; char* address; } QuuxState;
QuuxState spork_quux(FILE*);
Run Code Online (Sandbox Code Playgroud)
那么,如何正确地做到这一点?
Jos*_*phH 21
使用结构,但不要将定义公开给客户端.
即.在.h头文件中放:
typedef struct QuuxState QuuxState;
QuuxState *spork_quux(FILE*);
Run Code Online (Sandbox Code Playgroud)
并在.c实现文件中:
struct QuuxState
{
int state;
char* address;
};
QuuxState *spork_quuxFILE *f)
{
QuuxState *quuxState = calloc(1, sizeof(*quuxState));
if (!quuxState)
return NULL;
quuxState->state = ....;
........
return quuxState;
}
Run Code Online (Sandbox Code Playgroud)
这种方法的优点是:
唯一的缺点是你必须分配一块内存 - 但是假设你的库正在做任何不重要的事情(如果它正在进行文件I/O,那肯定是非平凡的),单个malloc的开销可以忽略不计.
您可能希望将上述函数重命名为"QuuxSpork_create",并添加更多函数来处理执行逐行工作并在完成后销毁状态.
void QuuxSpork_readLine(QuuxState *state)
{
....
}
void QuuxSpork_destroy(QuuxState *state)
{
free(state);
}
Run Code Online (Sandbox Code Playgroud)
像这样工作的库的随机示例是POSIX线程库,pthreads.