2009-04-23 13 views
6

プロセス間で文字列のスタックを共有する必要があります。私はboost :: interprocessを使うことに決めましたが、動かすことができません。私は何かを理解していないからだと確信しています。私はその例を踏襲しましたが、そのライブラリを使った経験がある人が自分のコードを見て、何が間違っているのかを教えていただければ幸いです。問題はうまくいくようですが、何度か反復した後は、読者プロセスと時にはライタープロセスの両方であらゆる種類の例外が発生します。 named_mutexを使用するように編集ブースト、共有メモリ、およびベクトル

using namespace boost::interprocess; 
class SharedMemoryWrapper 
{ 
public: 
    SharedMemoryWrapper(const std::string & name, bool server) : 
     m_name(name), 
     m_server(server) 
    { 
     if (server) 
     { 
      named_mutex::remove("named_mutex"); 
      shared_memory_object::remove(m_name.c_str()); 
      m_segment = new managed_shared_memory (create_only,name.c_str(),65536);   
      m_stackAllocator = new StringStackAllocator(m_segment->get_segment_manager()); 
      m_stack = m_segment->construct<StringStack>("MyStack")(*m_stackAllocator); 
     } 
     else 
     { 
      m_segment = new managed_shared_memory(open_only ,name.c_str()); 
      m_stack = m_segment->find<StringStack>("MyStack").first; 
     } 
     m_mutex = new named_mutex(open_or_create, "named_mutex"); 
    } 

    ~SharedMemoryWrapper() 
    { 
     if (m_server) 
     { 
      named_mutex::remove("named_mutex"); 
      m_segment->destroy<StringStack>("MyStack"); 
      delete m_stackAllocator; 
      shared_memory_object::remove(m_name.c_str()); 
     } 
     delete m_mutex; 
     delete m_segment; 
    } 

    void push(const std::string & in) 
    { 
     scoped_lock<named_mutex> lock(*m_mutex); 
     boost::interprocess::string inStr(in.c_str()); 
     m_stack->push_back(inStr); 
    } 
    std::string pop() 
    { 
     scoped_lock<named_mutex> lock(*m_mutex); 
     std::string result = ""; 
     if (m_stack->size() > 0) 
     { 
      result = std::string(m_stack->begin()->c_str()); 
      m_stack->erase(m_stack->begin()); 
     } 
     return result; 
    } 
private: 
    typedef boost::interprocess::allocator<boost::interprocess::string, boost::interprocess::managed_shared_memory::segment_manager> StringStackAllocator; 
    typedef boost::interprocess::vector<boost::interprocess::string, StringStackAllocator> StringStack; 
    bool m_server; 
    std::string m_name; 
    boost::interprocess::managed_shared_memory * m_segment; 
    StringStackAllocator * m_stackAllocator; 
    StringStack * m_stack; 
    boost::interprocess::named_mutex * m_mutex; 
}; 

EDIT:ここに私の実装の簡易版です。元のコードは、間違っているinterprocess_mutexを使用していましたが、それは問題ではありませんでした。

EDIT2私はまた、ポイントまで機能することに注意する必要があります。ライタープロセスは、リーダが破損する前にいくつかの小さな文字列(または非常に大きな文字列)を押すことができます。リーダは、m_stack-> begin()行が有効な文字列を参照しないように分割します。それはごみです。そしてさらに実行すると例外がスローされます。

EDIT3クラスをstd :: stringではなくboost :: interprocess :: stringを使用するように変更しました。それでも読者は無効なメモリアドレスで失敗します。ここにリーダ/ライターです

//reader process 
SharedMemoryWrapper mem("MyMemory", true); 
std::string myString; 
int x = 5; 
do 
{ 
    myString = mem.pop(); 
    if (myString != "") 
    { 
     std::cout << myString << std::endl; 
    } 
} while (1); //while (myString != ""); 

//writer 
SharedMemoryWrapper mem("MyMemory", false); 
for (int i = 0; i < 1000000000; i++) 
{ 
    std::stringstream ss; 
    ss << i; //causes failure after few thousand iterations 
    //ss << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" << i; //causes immediate failure 
    mem.push(ss.str()); 
} 
return 0; 
+0

以前のポスターには大変申し訳ありません。私は間違って「削除」をクリックし、まったく同じ質問の元の投稿を消去しました。 – Budric

+1

元に戻すことはできませんか?それともそれは答えのためだけに働くのですか? –

+0

私はあなたのインラインメソッドのサイズでギャグを許可していますか?それとも、C++のnoobとしてマークしていますか? –

答えて

4

あなたの実装について私に飛び出したことはいくつかあります。一つは、名前付きmutexオブジェクトへのポインタの使用でしたが、ほとんどのboostライブラリのドキュメントは、ポインタを使用しないように後方に曲がる傾向がありました。これは、あなたが自分のテストケースを構築する際に取り組んだプログラムスニペットへの参照を求めています。私は同様の誤解がありました。時には、唯一の方法は、元に戻って一歩前進することです。私は壊滅的な変化に出くわす。

もう1つの疑問は、共用メモリ用の65kブロックの割り当てと、テストコード内での1000000000へのループで、それぞれの繰り返しに文字列をプッシュすることです。

最新のPCはマイクロ秒以上で1000命令を実行でき、Windowsのようなオペレーティングシステムでは15ミリ秒で実行量を減らすことができます。スタックをオーバーフローさせるのに時間がかかりません。それは、私の最初の推測ですが、物事はなぜか線引きされています。

P.S. 私の名前を私の実際の身元に似ているものに修正したばかりです。そして、あなたの質問に対する私の答えは、ブラウザのページの左上隅から見て、私たちの顔を見ていました! (もちろん、私は正しかったと推測していますが、これはこのビジネスのケースではしばしばありません)。

+0

私は、共有メモリを増やし、代わりにPoco :: SharedMemoryを使用しました。テストコードは決して多くの反復に達しませんでした。また、読者は、メモリを解放するスタックから物をポップする必要があります。 – Budric

+0

これは私が追随できなかった部分です。あるスレッドが別のスレッドに制御を与えるための具体的な場所や方法は見当たらないので、1つを実行してからもう一方のラウンドロビンを実行すると仮定しました。 Windowsは膨大な時間を費やしているので、15ミリ秒前にはバッファーがいっぱいになります。 C++のIOStreamsも頻繁にバッファリングされるので、出力の有無は誤解を招く可能性があります。私の理論をチェックする方法は、バッファの両側に "ガードゾーン"を置き、上書きを探します。とにかく計画を変更する正しい選択をしました。 –

-3

あなたの問題はまずはあなたの問題の正しいデザインではありません。しかし、私たちはあなたが最初に達成しようとしていることを知らないので、わかりません。

関連する問題