问题在于编码风格。如何创建外部功能但处理锁定的功能。
void Timer_start(Timer *t){ //this is a user facing function
if (t->state == Timer_paused){
Timer_resume(t);
} else {
Timer_initialize(t);
}
}
void Timer_resume(Timer *t){ //this is also a user facing function
Lock_acquire(t->lock);
//...do work
Lock_release(t->lock);
}
void Timer_initialize(Timer *t){ //and so is this
//...do work (just to illustrate the the functions arent necessarily simply wrapped with the locking functions)
Lock_acquire(t->lock);
//...do work
Lock_release(t->lock);
}
在示例中,Timer_start
应该包含在Lock_acquire
和Lock_release
中,就像其他两个函数一样,因为在状态检查后可能会立即中断。问题是我无法将函数包装在正确的锁定函数中,因为被调用的函数本身会获得锁定。是否有编码风格可以很好地处理这个问题?
答案 0 :(得分:2)
为什么不使用本地(静态)函数来执行_resume和_init的内容,然后所有外部函数都只有锁定并调用内部函数。
static void Timer_resume_impl(Timer *t) {
do work
}
static void Timer_initialize_impl(Timer *t) {
do work
}
void Timer_start(Timer *t) {
Lock_acquire(t->lock);
if (t->state == Timer_paused) {
Timer_resume_impl(t);
}
else {
Timer_initialize_impl(t);
}
Lock_release(t->lock);
}
void Timer_resume(Timer *t) {
Lock_acquire(t->lock);
Timer_resume_impl(t);
Lock_release(t->lock);
}
...
答案 1 :(得分:1)
您可以实施Timer_resume_unlocked
和Timer_start_unlocked
,这需要调用者负责锁定。然后让Timer_resume
和Timer_start
成为一个包装器,除了锁定和调用他们的_unlocked
对应者之外什么都不做。
您可以自行决定是否将_unlocked
个变体作为公共API的一部分,但通常情况下,用户最终会更希望这些变体。
另一个选择是,如果可能能够正确实施API,请为API的调用者保留适当的锁定。通常可以将一个愚蠢的“锁定所有”安全层添加到不使用锁的库中,但是当它变得多余时,从库的内容中删除锁定是不可能的。
或者您可以使用递归锁定(对good arguments有反对意见,但仍有可能)。