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);
}

この例では、状態チェックの直後に中断される可能性があるため、他の 2 つの関数と同様Timer_startにラップする必要があります。問題は、呼び出された関数自体がロックを取得するため、適切なロック関数で関数をラップできないことです。この問題をうまく処理するコーディング スタイルはありますか?Lock_acquireLock_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 およびを実装できますTimer_start_unlocked。これには、呼び出し元がロックを処理する必要があります。次に、ロックと対応する呼び出しのみを行うラッパーを作成Timer_resumeします。Timer_start_unlocked

バリアントをパブリック API の一部にするかどうかは、開発者次第です_unlockedが、一般的に、ユーザーは最終的にそれらを必要とする可能性が高くなります。

もう 1 つのオプションは、API の呼び出し側で正しく実装できる場合は、適切なロックを API の呼び出し側任せることです。通常、ロックを使用しないライブラリに「すべてをロックする」安全層を追加することは可能ですが、ロックが不必要であることが判明した場合、ライブラリの根幹からロックを削除することは不可能です。

または、再帰的ロックを使用することもできます (これには十分な反論がありますが、可能性は残っています)。

于 2013-01-27T19:11:23.583 に答える