C++ 标准库中提供的 std::string 类型有一些坑, 不小心使用的话很可能对程序性能造成影响. 例如字符串拼接这一常见简单的操作, 在 C++ 中大约有 4 种方式实现:

  1. + 操作符
  2. += 操作符
  3. append 成员
  4. stringstream<< 操作符
阅读全文 »

一个简单的 std::function 实现, 能够完成基本功能, 即可以代理:

  1. 普通函数
  2. bind 表达式
  3. lambda 表达式以及普通 functor
  4. 成员函数
  5. 成员变量

functor 存储部分使用继承体系擦除 functor 类型, 保留返回值以及参数列表类型. 核心的调用部分则是直接使用 std::invoke 实现, 同时也没有做 functor 大小的区分, 统一存在堆上.

阅读全文 »

「期值」是标准库为异步任务中返回值以及异常的传递提供的基础设施. 具体的做法是将这些值关联到共享的「future」对象上. 异步任务可以向这些期值对象中写入返回值或异常值, 异步任务的发起线程则可以通过这些期值对象等待, 读取, 检查其所需要的异步结果. 标准库中为上述功能提供的设施即 std::promisestd::future.

阅读全文 »

Condition variable 和 Semaphore 是并发编程中用于同步控制和交互的原语. 多个并发线程可以使用 Condition variable 彼此交互, 一些线程可以通过 Condition variable 等待 (wait) 其他线程的通知 (notification). Condition variable 总是和 mutex 关联使用. Semaphore 相比 Condition variable 更加轻量, 它用来限制多个线程对共享资源的并发访问.

阅读全文 »

mutex 即 mutual exclusion, 表示一种互斥语义. 所谓互斥, 实际上是指所有权的唯一性, 即同一时刻一个互斥量只能由一个所有者持有. 在并发语境中, 互斥量这一原语的所有者一般是「线程」, 它的作用是用于阻止多个线程同时访问共享的资源, 从而避免 data race 并为多个线程的执行提供实现「同步」的机制.

阅读全文 »

C++ 17 提供了两个编译时常量, 用于表示 CPU Cache 的一些参数. 合理使用这两个编译时常量可以避免在多级 Cache 结构的计算机上并发程序频繁访问同一个对象不同成员时可能发生的 伪共享 (false sharing) 问题.

阅读全文 »

C++ 11 及之后的版本中提供了一系列并发编程的工具和对并发控制原语的抽象封装, 如 thread, atomic, mutex, condition_varible 等. 本文介绍 thread 以及 jthread 的基本语义和功能, 它们在实际场景中的 best practice 和与之密切相关的编程模式不在本文讨论范围之内.

阅读全文 »

偶然在 vscode 的代码提示中看到了 thread_local 这个关键字, 心想 C++ 中什么时候提供了这种东西. 翻了下 cppreference 才知道早在 C++ 11 中就引入了这个修饰符, 用于声明线程生命周期. 趁此机会系统地看了下 C++ 变量的 4 种生命周期, 特此记录.

阅读全文 »
0%