
cpp
文章平均质量分 67
maohuazhu
后台开发工程师,编程爱好者。GitHub:https://github.com/neal-zhu
展开
-
glog 学习笔记(2)
glog 中有一个 Mutex 的简单封装(仅供内部使用,代码见 ./src/base/mutext.h)。其实按道理 mutex 封装是一个非常常见以及非常简单的 class,我相信任何有一定多线程开发经验的 cpp-er 都应该自己写过这个轮子。但是,glog 中这个 mutex 确提供了一个不同寻常的特性:支持 dynamic-initialization (即在 main() 调用前的全局构造函数中使用)。首先这里先简单解释下 Mutex 其要解决的场景:我们知道,因为 c++ 中构造函数的存在原创 2021-04-07 06:08:19 · 305 阅读 · 0 评论 -
glog 学习笔记(1)
glog 中,定义了两个宏DECLARE_VARIABLE 和 DEFINE_VARIABLE 用于支持声明、引入一些参数,来控制 glog 的运行时行为。其实现如下:#define DECLARE_VARIABLE(type, shorttype, name, tn) \ namespace fL##shorttype { \ extern GOOGLE_GLOG原创 2021-04-07 05:42:30 · 410 阅读 · 0 评论 -
使用 ucontext 实现用户态线程(下)
前面的文章介绍了 ucontext 相关函数的基本作用,我们已经知道如何用 getcontext 等函数实现基本的函数 yield & resume 的操作了。下面来看看如何实现一个简陋的用户态线程库吧!首先来看我们 thread 的定义:#define STACK_SIZE 4096typedef struct thread thread_t;struct thread { char stack[STACK_SIZE]; /* 协程运行栈 */ ucontext_t c原创 2021-02-06 12:04:21 · 448 阅读 · 1 评论 -
使用 ucontext 实现用户态线程(上)
用户态线程,或者称之为协程,因为具有更好的扩展性,在现在的服务端编程中越来越受到重视。今天的文章会介绍在 linux 系统下,如何使用 ucontext 来实现协程库。用户态实现线程库其实有两个常见的选择,其一是 setjmp,但是因为其要想做到协程之间的栈隔离,需要使用汇编语言,实在非大多数程序员所长,这里就不展开介绍了。另一个方案就是本文的主角 ucontext。来看一下今天的主角: #include <ucontext.h> int getcon原创 2021-02-05 21:37:30 · 480 阅读 · 0 评论 -
c 中的完美封装
面向对象编程为程序员的兵器库中添加了很多重型武器,比如:封装,多态等。通过封装,我们的模块可以强制所有的访问都使用其提供的接口,而不用对外暴露模块内部实现细节,同时也免于其自身状态被"出乎意料"的破坏。典型的做法就是将一个结构体的所有数据字段声明为 private,让其他模块只能通过其提供的 public 函数接口访问:class MyClass {public: int get_data() const { return data_; } int s...原创 2021-02-04 15:13:52 · 822 阅读 · 1 评论 -
一个优雅的 c 链表实现、使用方式
在阅读一些开源的 c 语言项目的时候,发现其实现链表的方式特别有趣且优雅,特此记录学习一下其本质是用一种类似继承的方式来实现 generic 的链表操作,但是我们都知道,c 是没有继承的,那么怎么做呢?首先来看我们的 "base class", 以及其的一些基本操作// circular list,双向循环链表typedef struct clist { clist_t *next; clist_t *prev;} clist_t;/* Insert element "...原创 2021-02-03 23:30:59 · 278 阅读 · 0 评论 -
手撸一个用户态线程库-为什么要使用协程(用户态线程)
本系列文章旨在带大家手撸一个简单的用户态线程(协程)库。本系列文章假设大家对多线程编程、EDSM(reactor 架构)有一定了解,所以并不会花太多精力去讲解这些内容。用户态线程,或者叫协程,越来越受到重视。这是为什么呢?多线程怎么就不香了呢?用户态为什么要重新造轮子,费劲的去实现一个用户态线程库呢?这背后到底是到的的沦丧,还是 KPI 的扭曲?下面我们来简单探讨一下。多线程编程的局限传统的多线程网络编程中,往往会使用一个内核线程来完整处理一个用户请求,大概伪代码如下:void HandleConn原创 2020-12-16 23:35:52 · 546 阅读 · 0 评论 -
leveldb深入浅出
leveldb简介LevelDB 是一个快速的提供持久化存储的 key/value(byte array) 存储数据库,可以把它理解为一个存储在本地磁盘的超大 map<string, string>。其局限性有:不是一个关系型数据库,不支持 sql 查询,不支持索引不支持进程级别的并发不支持类似 memcached、redis 的 c/s 架构leveldb 的整体架...原创 2019-09-15 11:48:46 · 499 阅读 · 0 评论 -
一个线程安全的 lrucache 实现 --- 读 leveldb 源码
缓存是计算机的每一个层次中都是一个非常重要的概念,缓存的存在可以大大提高软件的运行速度。Least Recently Used(lru) cache 即最近最久未使用的缓存,多见与页面置换算法,lru 缓存算法在缓存的大小达到最大值之后,换出最早未被使用的缓存。在阅读 leveldb 的源代码的时候,发现其中的 cache 类正是一个线程安全的 lru-cache 实现,代码非常优雅。笔者读完之...原创 2018-03-10 23:49:24 · 1727 阅读 · 0 评论 -
c++ compile-time 检测两个类型之间是否可以转化
在学习《modern c++ design》的时候,学习到了如何在 compile-time 检测两个类型之间是否可以转化。 这里的转换,既包括 int,long,double 这些数据类型之间的转换,也包括基类和子类之间的转换(也就是两个类之前是否存在 class A 继承自 class B)。但是这篇文章最核心的点在于 compile-time 这个限定词。因为这些检测是在 co...原创 2018-02-23 22:18:23 · 532 阅读 · 0 评论 -
对象工厂(2)---一个泛化的工厂类
在我的上一篇博客对象工厂(1)---和万恶的 switch 说再见中,我们通过使用函数指针索引的方法,为我们的工厂类代码中消除了 switch 语句。本篇博客的目标是将实现一个泛化的工厂类,实现代码复用。下面让我们先分析一下在对象工厂(1)---和万恶的 switch 说再见中的工厂类的几个主要角色:Abstract 基类(文中的 Shape),通过操作这个基类的指针,整个系统实现了运行期多态Co...原创 2018-02-28 11:33:32 · 253 阅读 · 0 评论 -
对象工厂(1)---和万恶的 switch 说再见
当系统中存在某抽象基类中有很多具体子类,一个简单实用的策略是创建对象的逻辑封装到一个工厂方法中。这样,可以在不影响客户端代码的情况下扩展具体子类。但是一个低质量的实现(比如像下面的代码,使用了 switch 语句),会导致编译的高耦合以及扩展的高成本,通过阅读 《modern c++ design》一书,看到了一个比较优雅的解决方法。现在假设我们要实现一个图形管理系统,其中 Shape 是抽象基类...原创 2018-02-27 23:01:17 · 512 阅读 · 0 评论