2012-01-14 11 views
4

小さなサーバーアプリケーションを作るためにlibconfig ++とスレッドを使っています。私の考えは、ミューテックスを持つラッパーとして機能する別のクラスを作成することですので、ポイントは、libconfig++ is not thread safeあり、このような何か:私はその変数のためにそのlibconfig supports plenty of typesを実現するまでC++ライブラリをマルチスレッド化する

class app_config { 
public: 
    app_config(); 
    /* Here be my problems. */ 
    void set(); 
    void get(); 
    virtual ~app_config(); 

private: 
    Config cfg; 
    boost::mutex *cfg_mutex; 
}; 

は今、これはすべて良いです。そして、私たちの主人公(私)が、この仕事を得るために何らかの形で彼に何かを示すことを望んでいる親切な心で、C + +の達人を探して自分自身を見つけたとき。

基本的に、getset機能が設定ファイルの変数へのパス(私はどちらか使用して気にしないだろう)と戻り値の型(またはset '内の第二引数を含むstd::stringchar*path変数が必要になります場合のように)...

いつもどんな助けにも感謝します。

ジュリアン

+2

ミューテックスのライフタイム管理には注意してください。 'app_config'をコピー不可能にして(mutex *の代わりに)' mutex'メンバを使うか、 'unique_ptr 'メンバを使って独自のコピー操作を定義して新しいインスタンスを作成してください。 –

+0

これは、ミューテックスがコピー不可能であるためです。ありがとう! –

答えて

1

このアプローチを使用することもできます。私はそれを使用するのがより難しく、それゆえに優れていると思う。 Libconfigインスタンスは、ラッパー内部のプライベートメンバーであり、ロックなしではアクセスできません。

#include <boost/thread/mutex.hpp> 
#include <boost/thread/locks.hpp> 
#include <boost/shared_ptr.hpp> 

class Libconfig { 
public: 
    int Get(const char*) { return 0; } 
}; 

class LibConfLock; 

class LibconfMultithreadingWrapper { 
    friend class LibConfLock; 
public: 
    LibconfMultithreadingWrapper() 
     :m_Libconfig(new Libconfig()) 
     ,m_Mutex(new boost::mutex()) 
    {} 

private: 
    boost::shared_ptr<Libconfig> m_Libconfig; 
    boost::shared_ptr<boost::mutex> m_Mutex; 
}; 

class LibConfLock { 
public: 
    LibConfLock(const LibconfMultithreadingWrapper& wrapper) 
     :m_Libconfig(wrapper.m_Libconfig) 
     ,m_Mutex(wrapper.m_Mutex) 
     ,m_Lock(new LockType(*m_Mutex)) 
    {} 
    Libconfig& GetLibconf() const { return *m_Libconfig; } 
private: 
    typedef boost::lock_guard<boost::mutex> LockType; 
    boost::shared_ptr<Libconfig> m_Libconfig; 
    boost::shared_ptr<boost::mutex> m_Mutex; 
    boost::shared_ptr<LockType> m_Lock; 
}; 

int main() { 
    LibconfMultithreadingWrapper wrapper; 
    int i = LibConfLock(wrapper).GetLibconf().Get("hallo"); 

    return i; 
} 
1

あなたはプライベートlibconfigインスタンスへのすべての関数呼び出しを転送するデコレータのクラスを書くことができます。つまり、デコレータに使用するすべての機能を追加する必要があります。 もう1つの可能性は、libconfigへの呼び出しを実際のロックを行うクラスに転送することです。

#include <boost/thread/mutex.hpp> 
#include <boost/thread/locks.hpp> 
#include <boost/bind.hpp> 

class MultithreadingWrapper { 
public: 
    template <class V, class T> 
    V ExecuteThreadSaveWithReturn(T func) { 
     boost::lock_guard<boost::mutex> l(m_Mutex); 
     return func(); 
    } 

    template <class T> 
    void ExecuteThreadSave(T func) { 
     boost::lock_guard<boost::mutex> l(m_Mutex); 
     func(); 
    } 

private: 
    boost::mutex m_Mutex; 
}; 

void f() {} 
void f(int) { } 
int f(int, int) { return 0; } 

int main() { 
    MultithreadingWrapper wrapper; 
    wrapper.ExecuteThreadSave(boost::bind(f)); 
    wrapper.ExecuteThreadSave(boost::bind(f, 1)); 
    int i = wrapper.ExecuteThreadSaveWithReturn<int>(boost::bind(f, 1, 1)); 
    return i; 
} 
+0

これは本当に良いアプローチですが、何か他の選択肢があるのを見てみたいと思っています。 EDIT:実際に例外が発生するのは何ですか? –

+0

@ JulianBayardoSpadafora例外はラッパーを介して伝搬するため、wrapper.ExecuteThreadSaveを呼び出す場所で例外を処理する必要があります。 ExecuteThreadSave関数の最後にロックが削除されるため、例外がスローされた場合でも、ロックはリセットされます。 –

関連する問題