C++ adapting a library for multithreading

2019-06-25 06:02发布

问题:

I'm working with libconfig++ and threads for making a small server application. The point is, libconfig++ is not thread safe, so my idea is to create another class which acts as a wrapper with a Mutex, something like this:

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

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

Now, this is all good until I realize that libconfig supports plenty of types for its variables. And thats when our protagonist (me) finds himself in search of any C++ guru with a kind heart willing to show him any way to get this working.

Essentially, the get and set functions would need a std::string or a char* path variable containing the path to the configuration file's variable (I wouldn't mind using either) and the return type (or the second argument in the set's case) should vary...

As always, any help will be appreciated.

Julian

回答1:

You could as well use this approach. I think it more difficult to missuse and therefore superior. The Libconfig instance is a private member inside of the wrapper and can't be accessed without a lock.

#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;
}


回答2:

You could write a decorator class that forwards all function calls to a private libconfig instance. This means you need to add all the functions you want to use to your decorator. Another possibility is to forward the call to libconfig to a class that does the actual locking.

#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;
}


标签: c++ oop