我们一直在项目中使用Boost的basic_lockable_adapter
和strict_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
是什么,但是需要知道当前正在执行的线程是否具有该锁(它不关心其他线程)。
答案 0 :(得分:2)
严格锁定/始终/拥有锁定(这就是使他们严格的原因)。
unique_lock
有owns_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。