排他の仕方

昨日書いた疑似コードだとwrlock中にreadに来たスレッドが全てlock(&m)で待機するため、循環検出の終了待ちスレッドが多いとスループットが一時的に悪化する。これを改善するためにはmutexが獲得出来なかった場合にただ待機するのではなく、再度rdlockしようと挑戦した方が良いだろう。

#define NOLOCK 0
#define RDLOCK 1
#define MLOCK  2
#define SLEEP  100
void read() {
  int lock = NOLOCK;
  while (lock==NOLOCK) {
    if (!tryrdlock(&rw)) {
      lock = RDLOCK;
      break;
    } else if (!trylock(&m)) {
      lock = MLOCK;
      break;
    } else {
      usleep(SLEEP);
    }
  }
  //排他でのread作業
  switch (lock) {
  case RDLOCK:
    unlock(&rw);
    break;
  case MLOCK:
    unlock(&m);
    break;
  default:
    //エラー処理
    break;
  }
}

だんだん、不格好になってきたなぁ。もっと賢いやり方があるのではないか。少なくともscoped_lockなクラスにした方が良い気がする。