7

ハードウェアの周りでプロセス間同期が必要です。このコードは Windows と Linux で動作する必要があるため、Boost Interprocess ミューテックスでラップしています。すべてがうまく機能し、ミューテックスの放棄をチェックするための私の方法を受け入れます。こうなる可能性はあるので、それに備えなければなりません。

私はテストでミューテックスを放棄しました。確かに、scoped_lock を使用してミューテックスをロックすると、プロセスが無期限にブロックされます。これを回避する方法は、scoped_lock でタイムアウト メカニズムを使用することであると考えました (これを説明するメソッドをグーグルで検索するのに多くの時間が費やされたため、移植性の理由から、boost はこれをあまり処理しません)。

さらに苦労することなく、ここに私が持っているものがあります:

#include <boost/interprocess/sync/named_recursive_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>

typedef boost::interprocess::named_recursive_mutex MyMutex;
typedef boost::interprocess::scoped_lock<MyMutex> ScopedLock;

MyMutex* pGate = new MyMutex(boost::interprocess::open_or_create, "MutexName");

{
    // ScopedLock lock(*pGate); // this blocks indefinitely
    boost::posix_time::ptime timeout(boost::posix_time::microsec_clock::local_time() + boost::posix_time::seconds(10));
    ScopedLock lock(*pGate, timeout); // a 10 second timeout that returns immediately if the mutex is abandoned ?????
    if(!lock.owns()) {
        delete pGate;
        boost::interprocess::named_recursive_mutex::remove("MutexName");
        pGate = new MyMutex(boost::interprocess::open_or_create, "MutexName");
    }
}

少なくとも、それがアイデアです。3 つの興味深い点:

  • タイムアウト オブジェクトを使用せず、mutex を破棄すると、ScopedLock ctor が無期限にブロックされます。それは予想されます。
  • タイムアウトを使用し、mutex が放棄されると、ScopedLock ctor はすぐに戻り、mutex を所有していないことを通知します。わかりました、おそらくそれは正常ですが、私が言っている10秒も待っていないのはなぜですか?
  • ミューテックスが放棄されず、タイムアウトを使用すると、ScopedLock ctor はすぐに返され、ミューテックスをロックまたは所有権を取得できなかったことを伝え、ミューテックスを削除して再作成する動作を実行します。 . これは私が望むものではありません。

では、これらのオブジェクトを使用する際に何が欠けているのでしょうか? じっと見つめているのかもしれませんが、見えないので助けを求めています。

また、このハードウェアのしくみにより、プロセスが 10 秒以内にミューテックスの所有権を取得できない場合、ミューテックスは破棄されることにも言及する必要があります。実際、おそらく 50 ミリ秒または 60 ミリ秒ほど待つこともできますが、10 秒は寛大さの「ラウンド」数としては適切です。

Visual Studio 2010 を使用して Windows 7 でコンパイルしています。

ありがとう、アンディ

4

5 に答える 5

5

タイムアウト オブジェクトを使用せず、mutex を破棄すると、ScopedLock ctor が無期限にブロックされます。それは予想通り

問題の最善の解決策は、ブーストが堅牢なミューテックスをサポートしている場合です。ただし、Boost は現在、堅牢なミューテックスをサポートしていません。堅牢なミューテックスをエミュレートする計画しかありません。それをネイティブでサポートしているのは Linux だけだからです。エミュレーションは、ライブラリの作成者である Ion Gaztanaga によって計画されたばかりです。ブースト ライブラリへの rubust ミューテックスのハッキングの可能性について、このリンクを確認してください: http://boost.2283326.n4.nabble.com/boost-interprocess-gt-1-45-robust-mutexes-td3416151.html

その間、共有セグメントでアトミック変数を使用しようとするかもしれません。

このスタックオーバーフロー エントリも参照してください: 放棄された boost::interprocess::interprocess_mutex の所有権を取得する方法は?

タイムアウトを使用し、ミューテックスが放棄された場合、ScopedLock ctor はすぐに戻り、ミューテックスを所有していないことを通知します。わかりました、おそらくそれは正常ですが、私が言っている10秒も待っていないのはなぜですか?

これは非常に奇妙です。この動作は発生しないはずです。ただし: 時限ロックは、try ロックに関して実装されている可能性があります。 次のドキュメントを確認して ください。その後、false を返します。

inline bool windows_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
{
   sync_handles &handles =
      windows_intermodule_singleton<sync_handles>::get();
   //This can throw
   winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
   return mut.timed_lock(abs_time);
}

ミューテックスが破棄されているため、ハンドルを取得できない可能性があります。

ミューテックスが放棄されず、タイムアウトを使用すると、ScopedLock ctor はすぐに戻り、ミューテックスをロックまたは所有権を取得できなかったことを伝え、ミューテックスを削除して再作成する動作を実行します。 . これは私が望むものではありません。

これについてはよくわかりませんが、名前付きミューテックスは共有メモリを使用して実装されていると思います。Linux を使用している場合は、ファイル /dev/shm/MutexName を確認します。Linux では、boost::interprocess::named_recursive_mutex::remove などでファイル自体を削除しても、ファイル記述子は閉じられない限り有効なままです。

于 2013-04-02T20:07:02.963 に答える