- 博客(22)
- 收藏
- 关注
原创 从 TrinityCore 源码看 C++ 定时器设计
本文探讨了游戏服务器中定时器的核心作用及其实现方案。游戏服务器需要精确处理大量定时任务(如玩家状态更新、BOSS技能连招等),传统阻塞方式无法满足需求。文章分析了TrinityCore中的两种定时器实现:1)基于multimap红黑树的EventProcessor,支持高效任务调度与多态执行;2)TaskScheduler方案,采用std::multiset管理任务,通过上下文嵌套实现复杂定时逻辑。两种方案均避免线程阻塞,利用时间差计算精确触发任务,其中TaskScheduler通过共享指针机制实现任务上下
2026-03-08 18:10:08
431
原创 分布式锁原理与实现
时钟漂移(Clock Drift)指的是分布式系统中不同节点的物理时钟以不同速率运行的现象。即使所有机器都使用NTP同步,也无法保证时钟完全一致。分布式锁的核心就是在分布式环境下“抢一把唯一的钥匙”,确保同一时刻只有一个节点能访问共享资源。理论部分我们聊了它的四大特性(互斥、超时、可用性、容错),并对比了 Redis 和MySQL 这两种“间接实现”的优劣——它们能干活,但得自己解决高可用和一致性。
2026-03-07 16:17:21
406
原创 C++ 内存泄漏检测
内存泄漏指的是程序中已动态分配的内存由于某种原因未被释放或无法释放,导致系统可用内存持续减少的现象。本文系统阐述了内存泄漏的检测与定位方法,从理论定义到工程实践形成了完整的技术闭环。核心思路在于建立"分配-释放"的追踪机制:通过记录内存申请时的上下文信息(调用位置、内存地址、大小),并在释放时核销对应记录,最终以残留的日志文件作为泄漏定位的依据。两种技术路线宏替换法以编译期介入实现简单追踪,适用于开发调试阶段,但需重新编译且无法覆盖第三方库Hook机制。
2026-03-05 10:12:44
479
原创 C++ 死锁检测基础思路
死锁的现象举一个简单的例子,如下图所示,3个线程都在运行,且图中资源均一次只能被一个线程占用,线程A占用资源1,线程B占用资源2,线程C占用资源3,此时线程A不释放资源1且想去占用资源2,而线程B也不释放资源2并且想去占用资源3,而线程C同样不释放资源3去占用资源1。回到刚才的图我们可以发现,形成死锁后图中出现了环,也就是说我们可以将线程与资源占用关系抽象成图之后,检测图中是否形成环回路,只要有环,那就出现了死锁,进而采取下一步操作。而在使用死锁检测时,可以用一个独立的线程监控,不影响主程序性能。
2026-03-02 21:48:37
421
原创 C++ 定时器设计基础
使用I/O多路复用的一个原因是,定时任务与网络 I/O有相似性,网络 I/O 何时就绪我们是不知道的,也就是说从注册到触发 I/O 之间是一个异步的操作。reactor模型就是将对 I/O 的处理转换为对事件的处理,注册事件类型后,当 I/O 多路复用返回时,根据事件类型直接调用对应的接口。使用 epoll 的关键点就是 epoll_wait 的第四个参数 timeout,我们可以将计算出的等待时间填在这里,如果没有I/O事件的话,当阻塞到对应时间时,程序再向下执行对应定时任务的操作。
2026-02-28 17:34:21
721
原创 C++ 用户态网络缓冲区设计
用户态程度读取后发现包并不完整,需要扩容再次发起系统调用,读取内核缓冲区的内容,而此时由于没有 extra 数组,我们获取不到数据究竟有多大(extra设置的是 64KB 只要比这个小,读取出来我们就能知道内核缓冲区中数据的长度)。由于没有 ringbuffer 的取余绕回功能,所以当指针后移,前面的废弃空间越来越多,剩余的空闲区域不足,但整体空闲空间依然足够时,我们通过内部腾挪,将碎片化的空间合并到尾部,避免不必要的扩容,同时这样腾挪降低了腾挪次数。3. 频繁腾挪数据(使用 memmove),效率低。
2026-02-27 19:04:09
810
原创 C++无锁队列的实现
定义:一个队列,其 push 和 pop 操作不使用操作系统的锁(如Mutex)。核心优势高吞吐量:在特定场景下(尤其是SPSC和MPSC),它可以显著优于有锁队列。避免阻塞:线程不会因为争抢锁而被挂起。这在实时系统或延迟敏感的应用中至关重要。健壮性:避免了死锁和优先级反转问题。
2026-02-26 11:27:10
850
原创 C++ 原子操作:实践篇
如果 ref_count_ 不是指针,而是 std::atomic<std::size_t> ref_count_,那么每个 shared_ptr 在拷贝时(例如 shared_ptr p2 = p1;acquire 语义确保了:任何在其他线程上(使用 release 语义,例如 fetch_sub 中的acq_rel)释放引用的操作,在当前线程读取 ref_count_ 之前,都是可见的。内存操作(比如该线程对 *ptr_ 所做的修改),对于其他获取到这个 ref_count_ 的线程都是可见的。
2026-02-25 14:32:38
636
原创 C++ 原子操作:理论篇
当线程A在执行这个原子RMW时,其他核心(CPU)无法“插入”到这个过程的中间,它们必须等待A彻底完成后,才能读取到那个“已经完成”的新值。CPU 认为 data 的写入(可能导致缓存失效,很慢)和 ready 的写入(可能在另一个缓存行,很快)互不相关,它可能先执行 (2),再执行 (1)。确保一个核心的写入(特别是缓冲区里的写入)能及时“刷” (Flush) 出去,并让其他核心的缓存“失效” (Invalidate),从而对其他核心可见。这个“门”本身成了系统的性能瓶颈,CPU的并行性被白白浪费了。
2025-10-26 21:59:50
819
原创 手写MySQL连接池
维持和管理一定数量连接的池式结构,在使用时直接复用连接而非创建连接。因为创建连接的开销还是比较大的,服务器和MySQL创建连接的过程如下图所示:当一条连接建立之后,长时间不向MySQL发送数据的话,MySQL会将这条连接断开,这要求连接池在管理的时候需要定时发送心跳包,让MySQL知道这条连接是活跃的。所以连接池在管理连接时需要实现这一功能,但本文暂不涉及发送心跳包的内容讲解。
2025-10-25 20:00:00
1469
原创 手写线程池
首先区分一下进程和线程:进程是操作系统进行资源分配的基本单位,线程是操作系统进行 cpu 调度的基本单位。线程池是维持管理一定数量线程的池式结构。维持线程:让线程一直存在复用线程,减少创建销毁线程的开销。管理线程:有任务让休眠的线程唤醒,无任务将线程休眠不参与cpu的调度。一定数量的线程:操作系统通过cpu核心去运行线程的 1:1,核心数是有限的,线程如果不断增加,会带来线程切换的问题,线程数如果越来越多不但不会提升性能还会给操作系统带来负担。
2025-10-24 15:15:00
1054
原创 io_uring
定义与背景:io_uring 是 Linux 内核提供的一种高性能异步 I/O 框架,旨在解决传统异步 I/O 模型的性能瓶颈。
2025-05-21 11:00:58
763
原创 协程组件Ntyco学习笔记
协程是一种用同步编程思维实现异步操作的技术,主要用于提高I/O密集型任务的效率。它通过用户态调度和非抢占式切换,避免了线程切换的开销和回调地狱问题。协程的优点包括极小的切换开销和避免线程竞争,但其缺点是无法充分利用多核资源,适合I/O密集型任务而非CPU密集型任务。协程的实现涉及上下文切换、汇编指令、原语操作(如yield和resume)以及调度器管理。调度器通过epoll管理协程状态,确保高效执行。协程的使用场景包括高并发网络服务和游戏开发等。参考项目如NtyCo展示了协程的具体实现和应用。
2025-05-19 13:00:11
1988
原创 用epoll实现reactor模式
reactor是事件驱动的,其核心是不同的I/O事件对应不同的回调函数。不仅是 epoll,select 和poll,它们都是聚焦于I/O事件管理,实现对应的I/O操作。但是之前在了解 epoll 的时候,了解到 epoll 不也是事件驱动的吗?实际上还是有区别的:epoll 只是负责高效地监听 fd 上的事件,比如告诉应用程序哪些套接字有数据可读、哪些可以写入数据等。但是对于这些具体的事件要执行什么操作,epoll 并不关心。
2025-04-16 16:00:00
1036
原创 select、poll、epoll解析
是最早被引入的 I/O 多路复用机制,select 的工作原理是将 fd 集合 fd_set 从用户空间复制到内核空间,由内核检查 fd 的状态,将有状态变化的 fd 集合返回给用户空间。nfds:它是需要监视的最大 fd 值加 1。为什么要加 1 呢?因为 fd 是从 0 开始编号的,例如最大 fd 是 5,那么实际需要检查的位是从第 0 位到第 5 位,总共 6 个位,所以 nfds 应该是 6(5 + 1)。这一参数用于指定 select 函数检查的 fd 范围。
2025-04-14 18:46:38
706
原创 socket网络编程常用API不完全指南
虽然 struct sockaddr 通用性强,但是它的成员变量在实际使用时不够方便,所以通常会使用特定协议族的地址结构,例如 struct sockaddr_in(用于 IPv4), struct sockaddr_in6(用于 IPv6)和 struct sockaddr_un(用于 Unix 域套接字)。UNIX\Linux中的一切都是文件。不同的计算机系统可能采用不同的字节序来存储多字节数据,常见的字节序有大端字节序(Big - Endian)和小端字节序(Little - Endian)。
2025-04-13 18:58:49
1991
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅