2012-02-17 28 views
1

私はかなりシンプルなデザインだと思っています。複数のオブジェクトがあり、それぞれにstd :: mapが含まれており、アクセスするプロセスが複数あります。私は一度にこれらのマップのそれぞれに1つの挿入/消去だけがあることを確認したいと思います。クラスメンバーのmutexアサーションが失敗しました

私はboost :: threadとclass member mutexesについて読んでいます。そしてbindを使ってクラスメンバーに渡しました。これは私にはすべて新しいものです。私はa Dr. Dobbs articleの簡単な例題から始め、それを修正しようとしました。スレッド化されたオブジェクトがコピー不可能でなければならないため、あらゆる種類のコンパイラエラーが発生していました。それを読んだら、代わりにミューテックスへのポインタを保持することで面倒を避けることができると決めました。だから今、私は次のエラーで結果に過ぎずコンパイルしたコードを持っている:

/usr/include/boost/shared_ptr.hpp:419: 
    T* boost::shared_ptr< <template-parameter-1-1> >::operator->() const 
    [with T = boost::mutex]: Assertion `px != 0' failed. Abort 

は、今私は本当にこだわっていると、本当にコードだけでなく、私が間違って概念的に行くよどこにコメントを助けいただければ幸いです。私はこれらの問題の周りにいくつか答えられた質問が既にあることを知っていますが、私はまだ何かが欠けていると思います。

#include <boost/thread/thread.hpp> 
#include <boost/thread/mutex.hpp> 
#include <boost/bind.hpp> 
#include <boost/shared_ptr.hpp> 
#include <iostream> 
#include <map> 

using namespace std; 

class Threaded { 
public: 
    std::map<int,int> _tsMap; 

    void count(int id) { 
    for (int i = 0; i < 100; ++i) { 
     _mx->lock(); 
     //std::cout << id << ": " << i << std::endl;  
     _tsMap[i] ++; 
     _mx->unlock(); 
    } 
    } 

private: 
    boost::shared_ptr<boost::mutex> _mx; 
}; 


int main(int argc, char* argv[]) { 
    Threaded th; 
    int i = 1; 
    boost::thread thrd1(boost::bind(&Threaded::count, &th, 1)); 
    //boost::thread thrd2(boost::bind(&th.count, 2)); 
    thrd1.join(); 
    //thrd2.join(); 

    return 0; 
} 

答えて

2

に見えます私の答えを参照してください。現状では(このコードをそのまま実行したと仮定して)、Threadedのデフォルトのコンストラクタはshared_ptrのデフォルトのコンストラクタを呼び出し、NULLポインタを返します(count()関数で逆参照されます)。

そして、あなたが同様にあなたのカウント機能から引数を削除することができ

Threaded::Threaded(int id) 
    : _mx(new boost::mutex()) 
    , _mID(id) 
{ 
} 

+0

うーん、それは私の馬鹿だった。問題を解決し、コードが適切に動作しているように見えます。今、このアプローチは間違っていますか?以下のravenspointの答えに従って、クラスの外側にミューテックスを格納する方が好きなのはなぜですか?これははるかに便利で論理的です – confusedCoder

1

ミューテックスは正当な理由でコピーできません。ミューテックスへのポインタを使用してコンパイラを超越しようとするのは、本当に悪い考えです。成功した場合、コンパイラは問題に気づくことはできませんが、それでもそこにあり、実行時にあなたを変えてくれるでしょう。

は2つのソリューション

  • ストア静的
  • 店としてあなたのクラスのミューテックスクラス外のミューテックスがあります。

両方に利点があります - 私は2番目を好む。

は、このいくつかのより多くの議論のために、あなたがで指すように意図され_mxミューテックスを作成し、あなたのスレッドクラスのコンストラクタが欠落しているように、ここでmutexes with objects

+0

私は静的にすることはできません。なぜなら、各オブジェクトがそれ自身のマップを独立して同時に処理したいからです。あなたのリンクにはポインタオプションはありません。このアプローチで何が問題になっていますか? – confusedCoder

1

概念的に、私はあなたが問題を持っていると思うのstdをコピーする:: shared_ptrのだろう次のラインに沿って、コンストラクタを追加する必要があります。参照カウントを増やすだけです。異なるオブジェクトはすべて、同じ根底にあるミューテックスを使用します。つまり、whenevあなたのオブジェクトの1つが使用され、残りのいずれも使用することはできません。

一方、他のオブジェクトのミューテックスガードとは関係のない独自のミューテックスガードを得るには、各オブジェクトが必要です。

あなたが必要とするのは、クラスprivateセクションに定義されているmutexをそのまま保つことですが、コピーコンストラクタとコピー代入演算子をオーバーロードして、最初から新しいものを作成しますコピー/割り当て元のオブジェクト。

関連する問題