2012-01-14 48 views
4

我正在使用libconfig ++和线程来制作小型服务器应用程序。问题的关键是,libconfig++ is not thread safe,所以我的想法是创建另一个类,用作与互斥的包装,像这样的东西: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; 
}; 

现在,这是所有的好,直到我意识到libconfig supports plenty of types其变量。而那时候,我们的主角(我)发现自己正在寻找任何C++大师,并以一种善意的心态向他展示如何实现这一目标。

实质上,getset功能将需要含有在set“路径到配置文件的变量(I不会介意使用任一)和返回类型(或者第二个参数中std::stringchar*path可变s)的情况应该有所不同...

一如既往,任何帮助将不胜感激。

朱利安

+2

请注意互斥体的生命周期管理。使'app_config'不可复制并使用'mutex'成员(而不是'mutex *')或使用'unique_ptr '成员并定义您自己的复制操作来创建新实例。 – 2012-01-14 03:28:43

+0

哦,这是因为互斥体是不可复制的,对吗?谢谢!。 – 2012-01-14 03:33:02

回答

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实例的装饰类。这意味着你需要添加你想用于装饰器的所有功能。 另一种可能性是将调用转发给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

这是一个非常好的方法,但我仍然保持这个问题的开放性,有兴趣看看还有其他的替代方案。 编辑:异常会发生什么? – 2012-01-14 04:14:48

+0

@JulianBayardoSpadafora异常将通过包装器传播,应在您调用wrapper.ExecuteThreadSave的地方处理。即使在ExecuteThreadSave函数末尾的锁被删除时引发异常,锁也将被重置。 – 2012-01-14 04:35:53