1

问题是关于编码风格。如何创建面向外部但能很好地处理锁定的功能。

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因为在状态检查后可能会立即被中断。问题是我无法将函数包装在正确的锁定函数中,因为被调用的函数本身会获取锁定。是否有一种编码风格可以很好地处理这个问题?

4

2 回答 2

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);
}
... 
于 2013-01-27T19:05:09.353 回答
1

您可以实现Timer_resume_unlocked and Timer_start_unlocked,这将要求调用者负责锁定。然后制作Timer_resumeTimer_start成为一个包装器,除了锁定和调用它们的对应物之外什么都不做_unlocked

是否将_unlocked变体作为公共 API 的一部分由您自己决定,但通常,用户最终比您希望的更可能需要它们。

如果可以在 API 的调用者一方正确实施,另一种选择是将适当的锁定留给 API 的调用。通常可以向不使用锁的库添加一个愚蠢的“锁定所有内容”安全层,但是当它被证明是多余的时,不可能从库的内部删除锁定。

或者你可以使用递归锁定(有很好的反对它的论据,但它仍然是一种可能性)。

于 2013-01-27T19:11:23.583 回答