前言
本文给出了一个自定义clang-tidy checker的实例,并介绍了引入该实例的背景和原因,旨在帮助读者以此为蓝本快速开发own clang-tidy checker。
本文并不对clang-tidy的基本使用做过多介绍,不熟悉的读者可以阅读官方文档。
此外,本文同样可以视作对write our own checkers的补充说明。
本文给出了一个自定义clang-tidy checker的实例,并介绍了引入该实例的背景和原因,旨在帮助读者以此为蓝本快速开发own clang-tidy checker。
本文并不对clang-tidy的基本使用做过多介绍,不熟悉的读者可以阅读官方文档。
此外,本文同样可以视作对write our own checkers的补充说明。
为了演示一些在设计无锁数据结构中用到的技术,本节将给出一系列简单数据结构的无锁实现。
如前文所述,无锁结构依赖原子操作和相关的内存顺序保证来确保数据以正确的顺序对其他线程可见。在本节之初,所有的原子操作将使用默认的memory_order_seq_cst
内存顺序,因为它最好理解(所有的memory_order_seq_cst
操作构成一个全序),但后续将逐渐减少约束至memory_order_acquire
,memory_order_release
,甚至memory_order_relaxed
。
虽然实例中没有直接使用互斥锁,但需要注意,仅有std::atomic_flag
保证无锁实现。如C++内存模型与原子类型操作
一章所述,在某些平台上C++标准库内的原子类型可能是基于锁实现的,此时倒不如选择直接使用基于锁的数据结构。
一段经典的生产-消费场景代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <vector>
#include <atomic>
#include <iostream>
std::vector<int> data;
std::atomic<bool> data_ready(false);
void reader_thread() {
while(!data_ready.load()) {
std::this_thread::sleep(std::milliseconds(1));
}
std::cout<<"The answer="<<data[0]<<"\n";
}
void writer_thread() {
data.push_back(42);
data_ready=true;
}
这里我们利用原子操作,保证了写入操作必然“先发生于”读取操作。不过,原子操作对顺序要求还有其他选项,它们构成了原子操作间的各种关系,下文将一一说明。