Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何避免重复代码,包括std::map和std::mutex_C++ - Fatal编程技术网

C++ 如何避免重复代码,包括std::map和std::mutex

C++ 如何避免重复代码,包括std::map和std::mutex,c++,C++,我有一个类,包括一个映射和一个互斥。在每个成员函数中,互斥锁保护映射不受多线程访问此类对象的影响,例如: class bar { public: void hello() {} void set_something(int x) {} int get_something(int x, int y) { return x + y; } }; class foo { public: foo() { m_map[0]; m_ma

我有一个类,包括一个映射和一个互斥。在每个成员函数中,互斥锁保护映射不受多线程访问此类对象的影响,例如:

class bar
{
public:
    void hello() {}
    void set_something(int x) {}
    int get_something(int x, int y) { return x + y; }
};

class foo
{
public:
    foo()
    {
        m_map[0];
        m_map[1];
        m_map[2];
    }
    void hello(unsigned int index)
    {
        std::lock_guard<std::mutex> lock(m_mut);
        const auto iter = m_map.find(index);
        if (iter != m_map.end())
            iter->second.hello();
    }
    void set_something(unsigned int index, int x)
    {
        std::lock_guard<std::mutex> lock(m_mut);
        const auto iter = m_map.find(index);
        if (iter != m_map.end())
            iter->second.set_something(x);
    }
    int get_something(unsigned int index, int x, int y)
    {
        std::lock_guard<std::mutex> lock(m_mut);
        const auto iter = m_map.find(index);
        if (iter != m_map.end())
            return iter->second.get_something(x, y);
        return 0;
    }
private:
    std::mutex                  m_mut;
    std::map<unsigned int, bar> m_map;
};

有没有一种优雅的方法可以避免重复代码?

您可以将公共部分移动到do\u something中,并将functor传递到其中:

...
void do_something(const std::function<void(bar&)>& func)
{
    std::lock_guard<std::mutex> lock(m_mut);
    const auto iter = m_map.find(index);
    if (iter != m_map.end())
        func(std::ref(*iter));
}

int get_something(unsigned int index, int x, int y)
{
    do_something(std::bind(&bar::get_something, std::placeholders::_1, index, x, y));
}
...

一个问题-您是否需要仅使用互斥对象std::map或std::map及其元素进行保护?您可以考虑粒度

您可以将公共部分移动到do\u something中,并将functor传递到其中:

...
void do_something(const std::function<void(bar&)>& func)
{
    std::lock_guard<std::mutex> lock(m_mut);
    const auto iter = m_map.find(index);
    if (iter != m_map.end())
        func(std::ref(*iter));
}

int get_something(unsigned int index, int x, int y)
{
    do_something(std::bind(&bar::get_something, std::placeholders::_1, index, x, y));
}
...

一个问题-您是否需要仅使用互斥对象std::map或std::map及其元素进行保护?您可以考虑粒度

您可以使用代理和RAII,如下所示:

#include <iostream>
#include <mutex>
#include <map>

template < typename F, typename S> 
struct mutex_map {
    std::recursive_mutex m_;
    std::map<F,S> map_;

    struct Proxy {
        Proxy( std::map<F,S> & map, std::recursive_mutex &m ) : map_(&map), lock_(m) {
            std::cout << "lock\n";
        }
        ~Proxy() { std::cout << "unlock\n"; }
        std::map<F,S>* map_;
        std::unique_lock<std::recursive_mutex> lock_;

        std::map<F,S>* operator->() { return map_; }
    };

    Proxy operator->() {
        return { map_, m_ };
    }
};

int main() {
    mutex_map<int, int> mm;

    mm->emplace(1, 3);
    std::cout << (mm->find(1) == mm->end()) << "\n";
    std::cout << (mm->find(2) == mm->end()) << "\n";
}

您可以使用代理和RAII,如下所示:

#include <iostream>
#include <mutex>
#include <map>

template < typename F, typename S> 
struct mutex_map {
    std::recursive_mutex m_;
    std::map<F,S> map_;

    struct Proxy {
        Proxy( std::map<F,S> & map, std::recursive_mutex &m ) : map_(&map), lock_(m) {
            std::cout << "lock\n";
        }
        ~Proxy() { std::cout << "unlock\n"; }
        std::map<F,S>* map_;
        std::unique_lock<std::recursive_mutex> lock_;

        std::map<F,S>* operator->() { return map_; }
    };

    Proxy operator->() {
        return { map_, m_ };
    }
};

int main() {
    mutex_map<int, int> mm;

    mm->emplace(1, 3);
    std::cout << (mm->find(1) == mm->end()) << "\n";
    std::cout << (mm->find(2) == mm->end()) << "\n";
}

我只是编写简单的代码。在我的情况下,我只保护std::map,并实际使用ting::shared_mutexstd::shared_mutex。谢谢你的回答!一切都是可能的,如果您想使用共享的_timed _互斥锁来区分写锁和读锁,您应该在互斥锁映射中删除通用运算符->并添加两个不同的获取函数,这两个函数返回一个不同的代理来执行您想要的锁定。请注意,我的示例只是代理思想的展示。抱歉,但我认为这个答案对我来说也很好!我只是编写简单的代码。在我的情况下,我只保护std::map,并实际使用ting::shared_mutexstd::shared_mutex。谢谢你的回答!一切都是可能的,如果您想使用共享的_timed _互斥锁来区分写锁和读锁,您应该在互斥锁映射中删除通用运算符->并添加两个不同的获取函数,这两个函数返回一个不同的代理来执行您想要的锁定。请注意,我的示例只是代理思想的展示。抱歉,但我认为这个答案对我来说也很好!使用代理模式进行此操作非常棒!如果我的示例使用std::shared_mutex而不是std::mutex,那么它也可以工作吗?使用代理模式实现这一点真是太棒了!如果我的示例使用std::shared_mutex而不是std::mutex,它是否也有效?