北京出名做网站的公司国外有在线做设计方案的网站吗

张小明 2025/12/30 23:40:21
北京出名做网站的公司,国外有在线做设计方案的网站吗,北京住房与建设部网站,搭建公司网站教程在 ZLMediaKit/ZLToolKit 的架构中#xff0c;模块之间的解耦至关重要。NoticeCenter#xff08;通知中心#xff09;正是为此而生。它实现了一个观察者模式或发布-订阅模式#xff08;Publish-Subscribe Pattern#xff09;#xff0c;充当了整个系统的“中枢神经”模块之间的解耦至关重要。NoticeCenter通知中心正是为此而生。它实现了一个观察者模式或发布-订阅模式Publish-Subscribe Pattern充当了整个系统的“中枢神经”负责将事件从发生地精准地投递给感兴趣的监听者。1. 核心设计理念与原理NoticeCenter的核心目标是让事件的产生者Emitter不需要知道谁在监听事件的消费者Listener也不需要知道谁发出的事件。1.1 双层映射结构为了高效管理成千上万的事件NoticeCenter采用了双层 Hash Map的结构第一层事件层NoticeCenter内部维护一个unordered_mapKey 是事件名称stringValue 是EventDispatcher事件分发器。作用根据事件名快速找到对应的分发器。第二层监听层每个EventDispatcher内部维护一个unordered_multimapKey 是监听者标识void* tagValue 是回调函数Any。作用存储该特定事件的所有监听回调。1.2 类型擦除与变参模板C 是强类型语言但通用的事件中心需要支持任意参数的回调。NoticeCenter结合了以下技术Any类型类似于 C17 的std::any用于存储任意类型的函数对象std::function实现了回调函数的类型擦除。变参模板Variadic TemplatesemitEvent方法接受ArgsType ...args允许发射携带任意数量和类型参数的事件。2. 核心类分析2.1EventDispatcher(幕后英雄)它是实际干活的类对应“某一个特定事件”的管理者。职责存储、删除、触发监听器。关键点防死锁机制在emitEvent触发回调时它会先拷贝一份监听列表然后释放锁再遍历拷贝的列表执行回调。为什么这么做如果在回调函数中又调用了addListener或delListener如果不释放锁就会导致死锁Self-Deadlock。中断机制支持InterruptException。如果某个监听器抛出此异常事件广播将立即停止不再通知后续监听器。2.2NoticeCenter(大管家)它是单例模式Singleton的对外入口。职责管理所有的EventDispatcher。接口addListener: 注册监听。delListener: 移除监听支持按 tag 移除单个或按 tag 移除所有事件的监听。emitEvent: 发射事件。2.3NoticeHelper(语法糖)这是一个模板辅助类配合宏NOTICE_EMIT使用。作用简化代码书写利用模板推导自动匹配参数类型让调用看起来更像函数调用。3. 类图概览manages 1nstores callbacks 1n«Singleton»NoticeCenter-std::unordered_map _mapListener-std::recursive_mutex _mtxListenerstatic Instance()addListener(tag, event, func)delListener(tag, event)emitEvent(event, args...)EventDispatcher-std::unordered_multimap _mapListener-std::recursive_mutex _mtxListeneraddListener(tag, func)delListener(tag, empty)emitEvent(safe, args...)«Type Erasure»Anyset(value)get(safe)4. 关键实现细节解析4.1 线程安全与性能平衡NoticeCenter在多线程环境下被高频使用因此线程安全至关重要。使用了std::recursive_mutex递归锁。这允许同一个线程在持有锁的情况下再次获取锁防止在复杂的嵌套调用如回调中移除监听中发生死锁。Copy-On-Write (类似思想)如前所述EventDispatcher::emitEvent中{std::lock_guardstd::recursive_mutexlck(_mtxListener);copy_mapListener;// 1. 临界区内只做拷贝速度快}// 2. 临界区外执行回调避免阻塞其他线程的添加/删除操作for(autopr:copy){...}4.2tag指针的作用addListener的第一个参数是void *tag。通常用法传入this指针。目的当对象析构时需要取消它注册的所有监听。通过tag即对象的地址NoticeCenter可以快速定位并移除该对象注册的所有回调防止悬垂指针导致的崩溃。5. 使用场景与示例场景一系统启动/停止通知当服务器初始化完成或准备关闭时通知各个模块。监听者 (Listener):classPlayer{public:Player(){// 关注 SERVER_INIT 事件// tag 传 this方便析构时移除NoticeCenter::Instance().addListener(this,SERVER_INIT,[](intport,conststringip){printf(Server started at %s:%d\n,ip.c_str(),port);});}~Player(){// 移除该对象的所有监听NoticeCenter::Instance().delListener(this);}};触发者 (Emitter):voidstartServer(){intport8080;string ip0.0.0.0;// 广播事件参数自动透传NoticeCenter::Instance().emitEvent(SERVER_INIT,port,ip);}场景二使用宏简化调用ZLToolKit 提供了NOTICE_EMIT宏让代码更优雅。// 定义事件参数签名// 这里的 void(int, string) 对应回调函数的签名NOTICE_EMIT(void(int,string),SERVER_INIT,8080,0.0.0.0);场景三中断事件传播假设有一个鉴权事件如果第一个监听者鉴权失败不希望后续监听者继续处理。NoticeCenter::Instance().addListener(this,AUTH_USER,[](conststringuser){if(useradmin){// 鉴权通过}else{// 抛出中断异常后续的回调将不会被执行throwEventDispatcher::InterruptException();}});6. 总结NoticeCenter是 ZLToolKit 中一个短小精悍但功能强大的组件。优点解耦性强、线程安全、支持任意参数、支持事件中断。注意回调函数是在触发线程中执行的。如果回调处理耗时过长会阻塞触发线程。对于耗时操作建议在回调中抛转到线程池处理。务必在对象析构时调用delListener(this)否则会导致野指针回调崩溃。通过理解NoticeCenter你就能掌握 ZLMediaKit 中流媒体状态变化、Hook 机制等底层通信的脉络。7. C117.1 using和typedef的区别using可以直接定义模板函数的别名:templatetypename T using ptr std::unique_ptrT; ptrint p(new int(10)); //正确 templatetypename T typedef std::unique_ptrT ptr; //错误 templatetypename T struct A { typedef std::unique_ptrT ptr; }; Aint::ptr x(new int(10)); //正确7.2 function_traitsfunction_traits是 ZLToolKit 中一个非常核心的 C模板元编程Template Metaprogramming工具类。它的主要作用是类型萃取Type Extraction在编译期解析出任何“可调用对象”函数、函数指针、std::function、Lambda 表达式、仿函数、成员函数的详细类型信息例如返回值类型、参数个数、参数类型等。templatetypename T struct function_traits; //普通函数, lambda表达式 templatetypename Ret, typename... Args struct function_traitsRet(Args...) //特化版本 { public: enum { arity sizeof...(Args) }; typedef Ret function_type(Args...); typedef Ret return_type; using stl_function_type std::functionfunction_type; typedef Ret(*pointer)(Args...); templatesize_t I struct args { static_assert(I arity, index is out of range, index must less than sizeof Args); using type typename std::tuple_elementI, std::tupleArgs... ::type; }; }; //函数指针 templatetypename Ret, typename... Args struct function_traitsRet(*)(Args...) : function_traitsRet(Args...){}; //std::function template typename Ret, typename... Args struct function_traitsstd::functionRet(Args...) : function_traitsRet(Args...){}; //member function #define FUNCTION_TRAITS(...) \ template typename ReturnType, typename ClassType, typename... Args\ struct function_traitsReturnType(ClassType::*)(Args...) __VA_ARGS__ : function_traitsReturnType(Args...){}; \ FUNCTION_TRAITS() FUNCTION_TRAITS(const) FUNCTION_TRAITS(volatile) FUNCTION_TRAITS(const volatile) //函数对象 templatetypename Callable struct function_traits : function_traitsdecltype(Callable::operator()){};可以通过这个类获取将任何函数类型转为stl的function类型。也可以活获取参数类型。在noticeCenter里有如下使用templatetypename FUNC void addListener(void *tag, FUNC func) { using funType typename function_traitstypename std::remove_referenceFUNC::type::stl_function_type; std::shared_ptrvoid pListener(new funType(std::forwardFUNC(func)), [](void *ptr) { funType *obj (funType *) ptr; delete obj; }); std::lock_guardstd::recursive_mutex lck(_mtxListener); _mapListener.emplace(tag, pListener); }这里通过function_traits的stl_function_type得到stl的function类型并构造了该类型的对象。7.3 function可以存储各种函数、函数指针、lambda 表达式等可调用对象。例如你可以使用std::functionint(int, float)来存储一个参数类型为int和float返回值类型为int的可调用对象。将函数、函数指针、lambda 表达式等存储在一个变量中方便传递和调用在不确定可调用对象的具体类型的情况下接受各种类型的可调用对象在运行时动态绑定可调用对象用于实现回调函数等可以使用std::bind将函数或函数对象绑定到一个function变量中例如#include functional int func(int x, float y) { return static_castint(x y); } int func2(int x, int y, int z) { return x y z; } struct FuncObj { int operator()(int x, float y) { return static_castint(x * y); } }; int main() { std::functionint(int, float) f1 func; f1(1, 2.5f); // Output: 3 std::functionint(int, float) f2 [](int x, float y) { return static_castint(x * y); }; f2(3, 0.5f); // Output: 1 std::functionint(int, float) f3 std::bind(func, std::placeholders::_1, std::placeholders::_2); std::cout f1(1, 2.5f) std::endl; // Output: 3 std::functionint(int, float) f4 std::bind(FuncObj(), std::placeholders::_1, std::placeholders::_2); std::cout f4(3, 0.5f) std::endl; // Output: 1 std::functionint(int) f5 std::bind(func2, 1, 2, std::placeholders::_1); std::cout f5(3) std::endl; // Output: 6 return 0; }7.4 tuple_element可以用于提取元组类型中某一位置的元素的类型。using TupleType std::tupleint, float, double; using ElementType std::tuple_element1, TupleType::type; std::cout typeid(ElementType).name() std::endl; // Output: float
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

手机上有那种网站吗网站维护员

3.3 上下文的艺术(上):详解CLAUDE.md与AGENTS.md,让AI理解你的项目 引言 在AI原生开发中,如何让AI真正理解你的项目?答案就是上下文文档。CLAUDE.md和AGENTS.md是Claude Code中两个核心的上下文配置文件,它们就像项目的"说明书",告诉AI项目的结构、规范、风…

张小明 2025/12/28 14:15:13 网站建设

淮北网站网站建设购物网站建设公司

还在为AI视频生成的高门槛而烦恼吗?WAN2.2-14B-Rapid-AllInOne(简称AIO)通过革命性的技术突破,让普通消费级显卡也能轻松驾驭专业级视频创作。本文将带您深入了解这款模型的独特魅力,从基础配置到高级技巧,…

张小明 2025/12/28 15:10:53 网站建设

高质量的网站建设淮北发布

第一章:揭秘Open-AutoGLM如何操控微信:AI自动化办公的新一代秘密武器AI驱动的自动化革命 Open-AutoGLM 是基于大语言模型与自动化控制技术深度融合的创新框架,能够实现对桌面级应用的智能操控。其核心能力之一便是通过语义理解与操作编排&…

张小明 2025/12/28 15:37:55 网站建设

php网站欣赏宜兴网站设计

YOLOv8 ROS 2终极指南:一键实现机器人智能视觉目标检测 【免费下载链接】yolov8_ros 项目地址: https://gitcode.com/gh_mirrors/yo/yolov8_ros 想象一下,你的机器人突然能"看见"周围环境,不仅能识别物体,还能精…

张小明 2025/12/28 15:39:25 网站建设

廊坊建设公司网站个人政务公开网站建设工作总结

在智能驾驶技术快速演进的当下,开源自动驾驶项目正通过系统性的技术路线图重新定义行业边界。基于对openpilot项目深度技术解析,本文将从核心技术架构、开源生态构建和产业影响三个维度,深入剖析2025年自动驾驶技术发展的关键路径。 【免费下…

张小明 2025/12/28 16:25:33 网站建设

为什么网站百度搜不到国际局势最新消息今天

PyWebIO企业级实战指南:从零构建高可用Web应用系统 【免费下载链接】PyWebIO Write interactive web app in script way. 项目地址: https://gitcode.com/gh_mirrors/py/PyWebIO 在当今快速发展的数字化时代,企业对于Web应用开发效率和质量提出了…

张小明 2025/12/28 16:26:35 网站建设