首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么std::lock_guard/std::unique_lock不使用类型擦除?

为什么std::lock_guard/std::unique_lock不使用类型擦除?
EN

Stack Overflow用户
提问于 2016-09-09 16:32:57
回答 1查看 2.2K关注 0票数 21

为什么std::lock_guardstd::unique_lock必须将锁类型指定为模板参数?

考虑以下替代方案。首先,在detail命名空间中,存在类型擦除类(非模板抽象基类和模板派生类):

代码语言:javascript
复制
#include <type_traits>
#include <mutex>
#include <chrono>
#include <iostream>

namespace detail {

    struct locker_unlocker_base {
        virtual void lock() = 0;
        virtual void unlock() = 0;
    };

    template<class Mutex>
    struct locker_unlocker : public locker_unlocker_base {
        locker_unlocker(Mutex &m) : m_m{&m} {}
        virtual void lock() { m_m->lock(); }
        virtual void unlock() { m_m->unlock(); }
        Mutex *m_m;
    };
}

现在te_lock_guard,类型擦除锁保护,在构造时简单地放置一个正确类型的对象(没有动态内存分配):

代码语言:javascript
复制
class te_lock_guard {
public:
    template<class Mutex>
    te_lock_guard(Mutex &m) {
        new (&m_buf) detail::locker_unlocker<Mutex>(m);
        reinterpret_cast<detail::locker_unlocker_base *>(&m_buf)->lock();
    }
    ~te_lock_guard() {
        reinterpret_cast<detail::locker_unlocker_base *>(&m_buf)->unlock();
    }

private:
    std::aligned_storage<sizeof(detail::locker_unlocker<std::mutex>), alignof(detail::locker_unlocker<std::mutex>)>::type m_buf;
};

我已经检查了性能与标准库的类:

代码语言:javascript
复制
int main() {
    constexpr std::size_t num{999999};
    {
        std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
        for(size_t i = 0; i < num; ++i) {
            std::mutex m;
            te_lock_guard l(m);
        }
        std::chrono::steady_clock::time_point end= std::chrono::steady_clock::now();
        std::cout << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << std::endl;
    }
    {
        std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
        for(size_t i = 0; i < num; ++i) {
            std::mutex m;
            std::unique_lock<std::mutex> l(m);
        }
        std::chrono::steady_clock::time_point end= std::chrono::steady_clock::now();
        std::cout << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << std::endl;
    }
}

将g++与-O3一起使用时,不会出现统计上显著的性能损失。

EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39407213

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档