在进行智能锁之前,需要了解一下什么叫 锁,参考http://konin.iteye.com/blog/2333350
啥叫智能锁呢,就是我在想锁住资源的时候,就锁住,待资源使用完后,自动释放该锁,比如
{//锁生命周期开始
LockGuard<InfoOrderQueue> guard(m_queue);//加锁
}//锁生命周期结束,自动释放锁
上面这段代码中,m_queue是InfoOrderQueue类型的资源,需要加锁,LockGuard是智能锁,当生命周期结束的时候,自动释放锁,就是这么个道理,那么如何实现呢?
先说明一下,为什么会做到自动加锁,是因为LockGuard的构造函数里,调用了InfoOrderQueue类的接口进行加锁,也就是说,资源本身自带了锁功能,而LockGuard的作用仅仅是做了自动加锁与释放的功能,具体的加锁释放本事是在资源类里进行的。先看看 InfoOrderQueue的声明
es::Queue<InfoOrder> InfoOrderQueue;
template<class T, class Q = deque<T> >
class Queue {
public:
//输入队列
typedef Q ItemQueue;
//大小类型
typedef typename ItemQueue::size_type SizeType;
//元素类型
typedef T ValueType;
/**
* 构造函数
* @param highWaterMark 队列高水位标, 0表示不限制
*/
Queue(SizeType highWaterMark = 0) : _highWaterMark(highWaterMark), _lowCond(_mutex),
_highCond(_mutex) {}
/**
* 加锁
*/
void acquire() {
_mutex.acquire();
}
/**
* 尝试加锁
*/
bool tryAcquire() {
return _mutex.tryAcquire();
}
/**
* 解锁
*/
void release() {
_mutex.release();
}
/**
* 唤醒一个线程
*/
void signal() {
_lowCond.signal();
}
/**
* 唤醒所有等待队列的线程
*/
void broadcast() {
_lowCond.broadcast();
}
/**
* 添加输入请求到队尾, 调用者要先锁定队列
*/
void add(T inputItem) {
while (_highWaterMark > 0 && _queue.size() >= _highWaterMark) {
_highCond.wait();
}
_queue.push_back(inputItem);
_lowCond.signal();
}
/**
* 添加批量输入请求到队尾, 调用者要先锁定队列
*/
template<class Iterator> void add(Iterator first, Iterator last) {
for (Iterator iter = first; iter != last; ++iter) {
while (_highWaterMark > 0 && _queue.size() >= _highWaterMark) {
_highCond.wait();
}
_queue.push_back(*iter);
_lowCond.signal();
}
}
/**
* 获取队首元素, 调用者要先锁定队列
*/
const T& peek() {
while (_queue.empty()) {
_lowCond.wait();
}
return _queue.front();
}
/**
* 删除队首元素
*/
void pop() {
_queue.pop_front();
if (_highWaterMark > 0) {
_highCond.signal();
}
}
/**
* 获取队列元素个数
*/
SizeType size() const {
return _queue.size();
}
/**
* 获取队列是否为空
*/
bool empty() const {
return _queue.empty();
}
/**
* 获取高水位标
*/
SizeType getHighWaterMark() const {
return _highWaterMark;
}
/**
* 设置高水位标
*/
void setHighWaterMark(SizeType highWaterMark) {
_highWaterMark = highWaterMark;
}
/**
* 清空队列
*/
void clear() {
_queue.clear();
if (_highWaterMark > 0) {
_highCond.broadcast();
}
}
private:
SizeType _highWaterMark;
ItemQueue _queue;
Mutex _mutex;
Condition _lowCond;
Condition _highCond;
};
上面这段代码中用到了mutex,这个类的实现在开头给的连接中有介绍,Condition会在后面介绍
再看看LockGuard的实现
template<class LockType> class LockGuard {
public:
/**
* 构造函数
*/
LockGuard(LockType& lock) : _lock(lock), _acquired(false) {
_lock.acquire();
_acquired = true;
}
/**
* 构造函数
*/
LockGuard(LockType& lock, bool acquired) : _lock(lock), _acquired(acquired) {
if (!acquired) {
_lock.acquire();
_acquired = true;
}
}
/**
* 析构函数
*/
~LockGuard() {
if (_acquired) {
_lock.release();
}
}
/**
* 是否已经加锁
*/
bool isAcquired() const {
return _acquired;
}
/**
* 转型
*/
operator const void*() const {
return _acquired ? this : 0;
}
/**
* 加锁
*/
void acquire() {
_lock.acquire();
_acquired = true;
}
/**
* 解锁
*/
void release() {
_lock.release();
_acquired = false;
}
private:
LockType& _lock;
bool _acquired;
};