代码篇之onceToken
夏楚 edited this page 2023-02-17 17:24:09 +08:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

ZLMediaKit里面大量用到了一个名叫onceToken对象, 很多小伙伴对这个工具类不明就里,下面我在此解释下其作用: onceToken 主要使用C/C++的RAII思想确保在变量构造和析构时执行自定义代码主要应用场景有如下

  • 1、作为全局变量用在程序加载时执行特定代码例如生成默认配置文件
////////////HLS相关配置///////////
namespace Hls {
#define HLS_FIELD "hls."
//HLS切片时长,单位秒
const string kSegmentDuration = HLS_FIELD"segDur";
//HLS切片个数
const string kSegmentNum = HLS_FIELD"segNum";
//HLS切片从m3u8文件中移除后继续保留在磁盘上的个数
const string kSegmentRetain = HLS_FIELD"segRetain";
//HLS文件写缓存大小
const string kFileBufSize = HLS_FIELD"fileBufSize";
//录制文件路径
const string kFilePath = HLS_FIELD"filePath";

onceToken token([](){
	mINI::Instance()[kSegmentDuration] = 2;
	mINI::Instance()[kSegmentNum] = 3;
	mINI::Instance()[kSegmentRetain] = 5;
	mINI::Instance()[kFileBufSize] = 64 * 1024;
	mINI::Instance()[kFilePath] = "./www";
},nullptr);
} //namespace Hls
  • 2、作为static变量确保代码只执行一次
int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
	typedef void (HttpSession::*HttpCMDHandle)(int64_t &);
	static unordered_map<string, HttpCMDHandle> s_func_map;
	static onceToken token([]() {
		s_func_map.emplace("GET",&HttpSession::Handle_Req_GET);
		s_func_map.emplace("POST",&HttpSession::Handle_Req_POST);
	}, nullptr);

	//后续代码省略
}
  • 3、作为局部变量确保函数退出前做一些清理工作例如释放锁
    template<typename ...ArgsType>
    bool emitEvent(const string &strEvent,ArgsType &&...args){
		onceToken token([&] {
			//上锁记录锁定线程id
			_mtxListener.lock();
			if(_lock_depth++ == 0){
				_lock_thread = this_thread::get_id();
			}
		}, [&]() {
			//释放锁取消锁定线程id
			if(--_lock_depth == 0){
				_lock_thread = thread::id();
				if(_map_moved){
					//还原_mapListener
					_map_moved = false;
					_mapListener = std::move(_mapListenerTemp);
				}
			}
			_mtxListener.unlock();
		});

		//后续代码省略
    }

  • 4、这个对象取名源自pthread_once以及ios下的dispatch_once。