1背景
上一篇分析了HRingBuf,这一篇分析HFrameBuf。
2步骤
2.1 HFrameBuf
在src/util/hframe.h中有如下代码
class HFrameBuf : public HRingBuf {
public:
enum CacheFullPolicy {
SQUEEZE,
DISCARD,
} policy;
HFrameBuf() : HRingBuf() {
cache_num = DEFAULT_FRAME_CACHENUM;
policy = SQUEEZE;
}
void setCache(int num) {cache_num = num;}
void setPolicy(CacheFullPolicy policy) {this->policy = policy;}
int push(HFrame* pFrame);
int pop(HFrame* pFrame);
void clear();
int cache_num;
FrameStats frame_stats;
FrameInfo frame_info;
std::deque<HFrame> frames;
std::mutex mutex;
};
上面声明了三个方法push,pop,clear
2.1.1 push
int HFrameBuf::push(HFrame* pFrame) {
if (pFrame->isNull())
return -10;
frame_stats.push_cnt++;
std::lock_guard<std::mutex> locker(mutex);
if (frames.size() >= (size_t)cache_num) {
hlogd("frame cache full!");
if (policy == HFrameBuf::DISCARD) {
return -20; // note: cache full, discard frame
}
HFrame& frame = frames.front();
frames.pop_front();
free(frame.buf.len);
if (frame.userdata) {
hlogd("free userdata");
::free(frame.userdata);
frame.userdata = NULL;
}
}
int ret = 0;
if (isNull()) {
resize(pFrame->buf.len * cache_num);
ret = 1; // note: first push
frame_info.w = pFrame->w;
frame_info.h = pFrame->h;
frame_info.type = pFrame->type;
frame_info.bpp = pFrame->bpp;
}
HFrame frame;
frame.buf.base = alloc(pFrame->buf.len);
frame.buf.len = pFrame->buf.len;
frame.copy(*pFrame);
frames.push_back(frame);
frame_stats.push_ok_cnt++;
return ret;
}
C++标准库提供了类模板std::lock_guard<>,针对互斥类融合实现了RAII手法:在构造时给互斥加锁,在析构时解锁,从而保证互斥总被正确解锁。
std::scoped_lock是C++17中引入的,用于替代std::lock_guard,它可以同时管理多个互斥量,而无须担心死锁的问题。它在构造时尝试锁定所有给定的互斥量,并在析构时释放它们。
std::unique_lock比std::lock_guard更灵活。它不仅能自动管理锁的获取和释放,还可以在运行时手动控制锁的获取和释放。
上面可以保证push,pop,clear互斥。
利用互斥保护共享数据并不太简单,我们不能把std::lock_guard对象化作“铁拳”,对准每个成员函数施予“重击”。 一旦出现游离的指针或引用,这种保护就全部形同虚设。 不管成员函数通过什么“形式”——无论是返回值,还是输出参数(out parameter)——向调用者返回指针或引用,指向受保护的共享数据,就会危及共享数据安全。
上面代码进行了如下操作
- 检查是否满了
- 检查是否为空
- 深拷贝frame
- 加入队列
2.1.2 pop以及clear
int HFrameBuf::pop(HFrame* pFrame) {
frame_stats.pop_cnt++;
std::lock_guard<std::mutex> locker(mutex);
if (isNull())
return -10;
if (frames.size() == 0) {
hlogd("frame cache empty!");
return -20;
}
HFrame& frame = frames.front();
frames.pop_front();
free(frame.buf.len);
if (frame.isNull())
return -30;
pFrame->copy(frame);
frame_stats.pop_ok_cnt++;
return 0;
}
void HFrameBuf::clear() {
std::lock_guard<std::mutex> locker(mutex);
frames.clear();
HRingBuf::clear();
}
上面进行了如下操作
- 判断是否为空
- 判断是否有数据
- 出队列
- 判断数据是否取到
- 深拷贝
frame_stats.pop_cnt没加锁,没用到也无所谓