私はあなたの提案のように100%何も知りませんが、近くにあるいくつかの既存のインターフェースがあります:
pthread_rwlock_trywrlock()
多くの既存のr/wロックAPIには、 UN*Xシステムのように「trylock」インターフェースがあります。これらは待機なしであり、誰もそれを所有していないか、すでにそれを待っていない場合にのみ、ロックを取得します。
通常、この回転をロックに使用するか、試行コードを人為的に遅らせます(バックオフ)。つまり、次のようなコードがあります。
for (count = 0; count < MAX_SPINS && (locked = trywrlock(lock)); count++);
if (locked) {
delay(some_backoff);
wrlock(lock); /* or try spinning loop above again ? */
}
残念ながら、これはあなたが求めているものではありません。ロックは遅くても問題なく取得されますが、低優先度のライターはCPUでスピンするか、(おそらく不要な)バックオフのために遅延してロックを取得します。
Solarisカーネルにはrw_tryupgrade(9f)
、現在のスレッドがロック上の唯一のリーダーであり、ライターが待機していないかどうかをテストするために使用できるインターフェイスがあります。その場合は、ロックを排他的/書き込みにアップグレードします。つまり、次のようにコーディングします。
if (!rw_tryenter(lock, RW_WRITER)) {
rw_enter(lock, RW_READER); /* this might wait for a writer */
if (!rw_tryupgrade(lock)) { /* this fails if >1 reader / writer waiting */
/* do what you must to if you couldn't get in immediately */
}
}
これはあなたが求めているものに少し近いですが、それでもまったく同じではありません-失敗した場合は、リードロックをドロップし、場合によってはバックオフ(待機)し、リードロックを再取得して、アップグレードを試みる必要があります。そのプロセスもまた回転に相当します。
また、多くのUNIXシステムは、少なくとも実際には、スケジューリングの優先順位に従ってウェイターのウェイクアップを実行します。wrlock()
したがって、通常の待機中の呼び出しを試みる前に、スレッドの優先度を(必然的に、人為的に)最低にする必要があります。スケジューラがどのように機能するかによって、スレッドが待機している間に他の人が同じ書き込みロックを必要とする場合は、その前にそれを取得します。マルチプロセッサ/コアシステムでは、必ずしも保証されているわけではありませんが...
最後に、SymbianOS(Symbian ^ 3バージョン)には、RRWlock
ライターよりもリーダーを優先するように作成できるクラスがあります。これにより、リーダーが待機中/着信している場合に、ライターを意図的に飢えさせることができます。特定のロックだけでなく、特定のロックのすべてのライターに影響します。
恐れ入りますが、2つのライターウェイクアップキューを使用して、独自の優先ロックを作成する必要があります。