RAIIがリソース管理の最も効率的な方法ではなかった1つ以上の具体的な例を誰かに教えてもらえますか?その理由は何ですか?
5 に答える
RAII が解決策でなかった唯一のケースは、マルチスレッドのクリティカル リージョン ロック管理の場合です。一般に、重要な領域ロックを取得し (リソースを考慮してください)、RAII オブジェクトに保持することをお勧めします。
void push( Element e ) {
lock l(queue_mutex); // acquire on constructing, release on destructing
queue.push(e);
}
ただし、その目的で RAII を使用できない場合があります。特に、ループ条件で使用される変数が複数のスレッドによって共有され、ループ実行全体のロックを保持できない場合は、別のメカニズムでロックを取得および解放する必要があります。
void stop_thread() {
lock l(control_mutex);
exit = true;
}
void run() {
control_mutex.acquire();
while ( !exit ) { // exit is a boolean modified somewhere else
control_mutex.release();
// do work
control_mutex.acquire();
}
control_mutex.release();
}
今思うと(ab)usingでRAIIも使えるかも知れませんがoperator,
、考えたこともありませんでした。しかし、これは本当に自然ではないと思います:
void run() {
while ( lock(control_mutex), !exit ) {
// do work
}
}
答えは、私が想像できるものではないということだと思います...
編集: RAII を使用した同じ問題の他の解決策:
@マークランサム:
bool should_exit() const {
lock l(mutex);
return exit;
}
void run() {
while ( !should_exit() ) {
// do work
}
}
@ fnieto :
void run() {
while (true) {
{ lock l(mutex);
if (exit) break;
}
// do work
}
}
場合によっては、2 段階の初期化 (作成、初期化、使用) が必要になることがあります。
または 3 段階: 私たちの製品には、独立したオブジェクトのコレクションがあり、それぞれがスレッドを実行し、優先度継承キューを介して任意の数の他のオブジェクト (それ自体を含む) にサブスクライブできます。オブジェクトとそのサブスクリプションは、起動時に構成ファイルから読み取られます。構築時に、各オブジェクトは可能なすべて (ファイル、ソケットなど) を RAII しますが、オブジェクトは未知の順序で構築されるため、他のオブジェクトをサブスクライブすることはできません。したがって、すべてのオブジェクトが構築された後、すべての接続が確立される第 2 段階と、すべての接続が確立されるとスレッドが解放されてメッセージングが開始される第 3 段階があります。同様に、シャットダウンも多段階です。
RAII は、リソースの所有権が言語構成要素によって提供される保証を通じて定義および管理されることを意味します。
C++ の RAII のポイントは、リソース所有権ポリシーを実際に言語で強制できることです。RAII に代わるより少ない方法は、API が呼び出し元に (たとえば、コメントやその他のドキュメントを介して)特定の時間に操作を明示的に実行するようにアドバイスすることです。この種のポリシーは、言語によって強制できません。ACQUIRE()
RELEASE()
したがって、元の質問は、強制力のないリソース管理アプローチが RAII よりも望ましい場合があるかどうかを尋ねる別の方法です。私が考えることができる唯一のケースは、言語の既存のリソース管理構造を意図的に回避し、独自のフレームワークを作成している場合です。たとえば、ガベージ コレクトされたスクリプト言語インタープリターを実装しているとします。アトムの「仮想割り当て」は、メモリ ブロックでゲームをプレイする可能性があります。同様に、プールベースのアロケータは、プログラムが最終的にDESTROY_POOL()
操作を呼び出し、グローバルな結果をもたらすことを期待しています (つまり、そのプールから割り当てられたアイテムはすべて無効になります)。
リソースの解放が失敗する可能性がある場合、RAII はそのリソースを管理するのに十分ではない可能性があります (デストラクタはスローしないため)。ただし、RAII は依然としてそのソリューションの一部である可能性があります。
GC はプログラマーの循環データ構造のメモリを処理できますが、RAII ではプログラマーがどこかでサイクルを手動で中断する必要があります。