有可能确定是一个boost :: basic_lockable_adapter目前是否被锁定?

时间:2016-01-29 15:15:34

标签: c++ boost locking mutex

我们一直在项目中使用Boost的basic_lockable_adapterstrict_lock来进行线程同步。我们已经确定了可能导致僵局的情况,我们希望避免这种情况。如果我们能够检测到basic_lockable_adapter是否被锁定,我们可以断言并在开发期间捕获它。

这是我正在寻找的一个例子(这个代码是可编译的,除了一个函数不存在的事实):

#include <boost/thread/lockable_adapter.hpp>
#include <boost/thread/strict_lock.hpp>
#include <mutex>

class Controller : public boost::basic_lockable_adapter<std::recursive_mutex>
{
public:
    static Controller& instance() { static Controller instance; return instance; }
};

void check_for_lock()
{
    // is_locked() isn't real ... but I'd like that functionality somehow
    if (Controller::instance().is_locked())
        std::cout << "It's locked." << std::endl;
    else
        std::cout << "Not locked." << std::endl;
}

int main()
{
    check_for_lock();
    boost::strict_lock<Controller> lock(Controller::instance());
    check_for_lock();

    return 0;
}

是否可以实现等效的.is_locked()

修改 - 澄清

我忘了提一个重点。我们使用&#34;外部锁定&#34;范例,如Boost文档中所述。有了它,一个绝对需要持有锁的函数只需要一个引用作为参数 - 因此,如果你得到参数,你知道你有锁。

就我而言,情况恰恰相反。我想知道当前线程当前是否有锁,来自一个不期望strict_lock作为参数的函数,所以我可以断言或抛出。

所以:函数知道lockable_adapter是什么,但是需要知道当前正在执行的线程是否具有该锁(它不关心其他线程)。

2 个答案:

答案 0 :(得分:2)

严格锁定/始终/拥有锁定(这就是使他们严格的原因)。

unique_lockowns_lock()http://en.cppreference.com/w/cpp/thread/unique_lock/owns_lock。它也隐式转换为完全相同的bool

您可以静态确定泛型类型是否严格锁定。关于如何在boost文档中将通用锁类型拼凑在一起的大讨论: Allowing other strict locks

答案 1 :(得分:1)

我不相信你的目标是100%可行的,使用一个朴素的html, body, #map_canvas { height: 100%; width: 100%; margin: 0px; padding: 0px }。虽然您可以通过在当前线程和单独的线程上调用<script src="https://maps.googleapis.com/maps/api/js"></script> <input id="btn" type="button" value="change style" /> <div id="map_canvas"></div>来尝试测试锁,但分析这些结果不会给您一个明确的答案。一个原因是标准允许std::recursive_mutex虚假失败,即使互斥锁可用。另一个原因是在递归时存在实现定义的限制,之后try_lock()将失败。

您可以替换自己的互斥锁类型吗?如果是这样,那么你可以用你自己的类来包装try_lock(),该类记录持有锁的线程。例如:

try_lock()

在包装器类std::recursive_mutex中,#include <mutex> #include <thread> #include <boost/thread/lockable_adapter.hpp> #include <boost/thread/strict_lock.hpp> class MyMutex { std::recursive_mutex m_; std::mutex auxMutex_; std::thread::id id_; unsigned int count_; public: MyMutex() : count_(0) {} void lock() { m_.lock(); std::lock_guard<std::mutex> lock(auxMutex_); if (!count_++) id_ = std::this_thread::get_id(); } void unlock() { std::lock_guard<std::mutex> lock(auxMutex_); --count_; m_.unlock(); } bool try_lock() { if (m_.try_lock()) { std::lock_guard<std::mutex> lock(auxMutex_); if (!count_++) id_ = std::this_thread::get_id(); return true; } return false; } std::thread::id id() { std::lock_guard<std::mutex> lock(auxMutex_); return count_ ? id_ : std::thread::id(); } }; class Controller : public boost::basic_lockable_adapter<MyMutex> { // Allow access to protected lockable() member function. friend void check_for_lock(); public: static Controller& instance() { static Controller instance; return instance; } }; void check_for_lock() { auto& lockable = Controller::instance().lockable(); if (lockable.id() == std::this_thread::get_id()) std::cout << "locked in current thread" << std::endl; else std::cout << "not locked in current thread" << std::endl; } int main() { check_for_lock(); boost::strict_lock<Controller> lock(Controller::instance()); check_for_lock(); return 0; } 跟踪递归级别,MyMutex记录要锁定的最后一个线程。否则,锁操作调用将转发到实际的count_

从适配器获取对互斥锁的引用确实需要访问受保护的id_成员函数。因此我将std::recursive_mutex作为朋友功能,或者它可以成为会员功能。它的实现变得很简单,比较线程ID。