为了防止大家找不到代码,还是先贴一下项目链接:
GitHub - skyfireitdiy/cocpp at cocpp-0.1.0
前面一共介绍了三种互斥量(锁),普通互斥量 co_mutex、递归互斥量 co_recursive_mutex、共享互斥量(读写锁)co_recursive_mutex。
每种互斥量都对应了一种带超时限制的版本:co_timed_mutex,co_recursive_timed_mutex,co_shared_timed_mutex。
前两种很简单,都是模板 co_timed_addition 的一个特化版本,如下(分别定义于 include/cocpp/sync/co_timed_mutex.h 和 include/cocpp/sync/co_recursive_timed_mutex.h):
using co_timed_mutex = co_timed_addition<co_mutex>; // 时间互斥锁
using co_recursive_timed_mutex = co_timed_addition<co_recursive_mutex>; // 递归时间互斥锁
复制代码
co_shared_timed_mutex 要多几个接口,因此它是继承自 co_timed_addition<co_shared_mutex>
所以接下来我们重点分析一下 co_timed_addition 这个模板类。
co_timed_addition
这个模板类定义在 include/cocpp/sync/co_timed_addition.h:
template <class Lock>
class co_timed_addition : public Lock
{
public:
template <class Rep, class Period>
bool try_lock_for(const std::chrono::duration<Rep, Period>& timeout_duration); // 尝试加锁
template <class Clock, class Duration>
bool try_lock_until(const std::chrono::time_point<Clock, Duration>& timeout_time); // 尝试加锁
};
// 模板实现
template <class Lock>
template <class Rep, class Period>
bool co_timed_addition<Lock>::try_lock_for(const std::chrono::duration<Rep, Period>& timeout_duration)
{
return try_lock_until(std::chrono::high_resolution_clock::now() + timeout_duration);
}
template <class Lock>
template <class Clock, class Duration>
bool co_timed_addition<Lock>::try_lock_until(const std::chrono::time_point<Clock, Duration>& timeout_time)
{
do
{
if (Lock::try_lock())
{
return true;
}
co::current_env()->schedule_switch();
} while (std::chrono::high_resolution_clock::now() < timeout_time);
return false;
}
复制代码
这就是这个模板类的整个定义与实现了,为模板参数增加 try_lock_for 和 try_lock_until 两个函数,其实现依赖于 try_lock 接口。在指定时间到达之前会不断地尝试。直到到达指定的时间或者获取锁成功为止。
上面提到,co_shared_timed_mutex 继承自 co_timed_addition<co_shared_mutex>
co_shared_timed_mutex
其接口与实现如下(include/cocpp/sync/co_shared_timed_mutex.h):
class co_shared_timed_mutex : public co_timed_addition<co_shared_mutex>
{
public:
template <class Rep, class Period>
bool try_lock_shared_for(const std::chrono::duration<Rep, Period>& timeout_duration); // 尝试加共享锁
template <class Clock, class Duration>
bool try_lock_shared_until(const std::chrono::time_point<Clock, Duration>& timeout_time); // 尝试加共享锁
};
// 模板实现
template <class Rep, class Period>
bool co_shared_timed_mutex::try_lock_shared_for(const std::chrono::duration<Rep, Period>& timeout_duration)
{
return try_lock_shared_until(std::chrono::high_resolution_clock::now() + timeout_duration);
}
template <class Clock, class Duration>
bool co_shared_timed_mutex::try_lock_shared_until(const std::chrono::time_point<Clock, Duration>& timeout_time)
{
do
{
if (try_lock_shared())
{
return true;
}
co::current_env()->schedule_switch();
} while (std::chrono::high_resolution_clock::now() < timeout_time);
return false;
}
复制代码
在 co_timed_addition<co_shared_mutex>的基础上又增加了两个成员函数 try_lock_shared_for 和 try_lock_shared_until,其实现与 co_timed_addition 中的 try_lock_for、try_lock_until 异曲同工,这里就不做深入分析了。
总结
本文介绍了前面三种互斥量对应的带时限的版本,总体来说就是利用一个模板类为现有的实现增加接口,衍生出功能更丰富的类,这个编程技巧在很多功能封装场景下都挺有用的。
评论