C++ 现代教程二

4 篇文章 0 订阅
1 篇文章 0 订阅

线程支持库 - C++中文 - API参考文档

GitHub - microsoft/GSL: Guidelines Support Library

Fluent C++:奇异递归模板模式(CRTP) - 简书


#include <thread>
#include <iostream>
#include <unordered_map>
#include <future>
#include <functional>

// atomic 有两个功能:原子 & 内存序
// 原子的作用:保证对一个变量操作期间,其他线程不会对此变量操作,那就称为原子操作
// 内存序的作用:构造一个事件发生先后的顺序关系

// 大多数普通的变量都不用是原子的,只有一个变量被多个线程同时访问(且其中一个是有副作用的写访问)时,才需要把它变成原子变量
// 所有其他变量,如果也设为原子的话,CPU 的压力会非常大,必须时时刻刻提心吊胆,编译器也会难以优化
// 我们只需要把少数多个线程同时访问的变量设为原子的就可以,帮 CPU 和编译器明确哪些是需要保证多线程并发访问安全的

//  x86 TSO
// CPU,缓存,编译器优化 -> 导致乱序
// 对少数关键变量的内存访问,指定内存序,可以阻断优化,避免这些关键变量的乱序
// 而普通的无关紧要的变量的访问依然可以乱序执行

// seq_cst = Sequentially-Consistent 顺序一致模型,总是保证所有内存操作,在所有线程看起来都是同一个顺序
// acquire = 我命令你,如果另一个线程对该变量 release 过,请把他的修改对我当前线程可见
// release = 我命令你,之前当前线程的所有写入操作,必须对所有对该变量 acquire 的线程可见
// acq_rel = acquire + release
// relaxed = 无内存序,仅保证原子性
// https://www.apiref.com/cpp-zh/cpp/thread.html
void testAtomic() {
	// 保证原子性
	std::atomic_int flag = 0;
	std::packaged_task<int()> task([&]() {
		std::cout << "start from thread" << std::endl;
		while (flag.load(std::memory_order_relaxed) == 0) // 2 ldr [data]
			;
		std::cout << "end from thread" << std::endl;
		return 0;
		});
	// get the future of task
	std::future<int> result = task.get_future();    // run task in a thread
	std::thread(std::move(task)).detach();
	result.wait_for(std::chrono::seconds(1));
	std::cout << "waiting..." << std::endl;
	//flag.fetch_add(1, std::memory_order::relaxed);  // +=
	flag.store(1, std::memory_order_relaxed); // 1 str [data]  // =
	result.wait(); // block until future has arrived

	// 不相等保存,相等时不操作,更高性能
	int oldVal = flag.load(std::memory_order_acquire), newVal = 0;
	while (!flag.compare_exchange_weak(oldVal, newVal, std::memory_order_seq_cst, std::memory_order_relaxed))  // compare_exchange_strong
		;
}

/* cpp  CRTP 模式自动实现 clone
template <class Derived>
struct Pet {
	void feed() {
		Derived* that = static_cast<Derived*>(this);
		that->speak();
	}
};

struct CatPet : Pet<CatPet> {
	void speak() {
		puts("Meow!");
	}
};

struct DogPet : Pet<DogPet> {
	void speak() {
		puts("Bark!");
	}
};
*/

// 组件模式
struct GameObject;
struct Component {
	virtual void update(GameObject* go) = 0;
	virtual ~Component() = default;  // 注意!
};

struct GameObject {
	std::unordered_map<uint64_t, Component*> components;

	template <class ImplementT>
	void add(Component* component) {
		components.emplace_back(getTypeID<ImplementT>, component);
	}

	void update() {
		//for (auto&& c : components) {
		//	c->update(this);
		//}
	}

	template <class ImplementT>
	uint64_t getTypeID() {
		return typeid(ImplementT).hash_code();
	}

	template <class T>
	const T* getComponent() {
		auto matched = components.find(getTypeID<T>());
		if (matched == components.end())
			return nullptr;
		return static_cast<const T*>(matched->second.get());
	}
};

//MVC 模式是一种架构模式,它将应用程序分为三个核心部分:模型(Model)、视图(View)和控制器(Controller),通过分离应用程序的输入、处理和输出来提高应用程序的可维护性和可扩展性。
//
//- 模型(Model):负责处理数据和业务逻辑,通常由数据结构和数据库组成。
//- 视图(View):负责展示数据和用户界面,通常由 HTML、CSS 和 JavaScript 组成。
//- 控制器(Controller):负责处理用户交互和调度模型和视图,通常由后端语言(如 PHP、Java 等)实现。

// C++20 开始
// Student stu{.name = "小彭老师", .age = 24, .id = 9999};

// 在 map 中使用 `[]` 查找元素,如果不存在,会自动创建一个默认值

// 多返回值用结构体替换,禁用tuple
struct from_chars_result {
	const char* ptr;
	int ec;
};

from_chars_result from_chars(const char* first, const char* last, int& value);

// 常量数组传参
//template <class Arr>
//concept has_data_size = requires (Arr arr) {
//	{ arr.data() } -> std::convertible_to<char*>;
//	{ arr.size() } -> std::same_as<size_t>;
//};

struct Span {
char* data;
size_t size;

template <size_t N>
Span(char(&buf)[N]) : data(buf), size(N) {}
template <size_t N>
Span(std::array<char, N>& arr) : data(arr.data()), size(N) {}

Span(std::vector<char>& vec) : data(vec.data()), size(vec.size()) {}

// 如果有需要,也可以显式写出 Span(buf, 30) 从首地址和长度构造出一个 Span 来
explicit Span(char* data, size_t size) : data(data), size(size) {}

//template <has_data_size Arr>
//Span(Arr&& arr) : data(arr.data()), size(arr.size()) {}

Span subspan(size_t start, size_t length = (size_t)-1) const {
	if (start > size)  // 如果起始位置超出范围,则抛出异常
		throw std::out_of_range("subspan start out of range");
	auto restSize = size - start;
	if (length > restSize) // 如果长度超过上限,则自动截断
		length = restSize;
	return Span(data + start, restSize + length);
}
};

template <class B>
struct GunWithBullet {
	static_assert(is_base_of<Bullet, B>::value, "B 必须是 Bullet 的子类");
};

// finally
template <class Callback>
struct Finally {
	Callback func;
	bool valid;

	Finally() : func(), valid(false) {}

	Finally(Callback func) : func(func), valid(true) {
	}

	Finally(Finally&& that) noexcept : func(std::move(that.func)), valid(that.valid) {
		that.valid = false; // 如果要支持移动语义,必须有个 bool 变量表示空状态!
	}

	Finally& operator=(Finally&& that) noexcept {
		if (this != &that) {
			if (valid) {
				func();
			}
			func = std::move(that.func);
			valid = that.valid;
			that.valid = false;
		}
		return *this;
	}

	void cancel() {
		valid = false;
	}

	void trigger() {
		if (valid) {
			func();
		}
		valid = false;
	}

	~Finally() {
		if (valid) {
			func();
		}
	}
};

template <class Callback> // C++17 CTAD
Finally(Callback) -> Finally<Callback>;

// https://github.com/microsoft/GSL   指针区分
void test() {
	Finally cb = [] {
		std::cout << ("调用了 Finally 回调") << std::endl;
		};
	std::shared_ptr<void> dtor(nullptr, [](void*) {std::cout << "test ~ctor" << "\n"; });
	testAtomic();
}

输出

start from thread
waiting...
end from thread

其它

CRTP (Curiously Recurring Template Pattern / 奇异递归模板模式)。基类模板参数包含派生类型的,这种就是传说中的 CRTP。包含派生类型是为了能调用派生类的某些函数
decltype(a)   返回 A const &
std::decay_t<decltype(a)>   返回 A

参考

现代 C++ 使用教程-CSDN博客

- [C++ 官方文档](https://en.cppreference.com/w/)
- [C++ 核心开发规范](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md)
- [Effective Mordern C++ 中文版](https://github.com/kelthuzadx/EffectiveModernCppChinese/blob/master/4.SmartPointers/item22.md)
- [热心观众整理的学习资料](https://github.com/jiayaozhang/OpenVDB_and_TBB)
- [HackingCpp 图文教程](https://hackingcpp.com/)
- [LearnCpp 基础教程](https://www.learncpp.com/cpp-tutorial/)
- [LearnCpp 中文版](https://learncpp-cn.github.io/)
- [Performance Analysis and Tuning on Modern CPUs](http://faculty.cs.niu.edu/~winans/notes/patmc.pdf)
- [C++ 并发编程实战](https://www.bookstack.cn/read/Cpp_Concurrency_In_Action/README.md)
- [深入理解计算机原理 (CSAPP)](http://csapp.cs.cmu.edu/)
- [并行体系结构与编程 (CMU 15-418)](https://www.bilibili.com/video/av48153629/)
- [因特尔 TBB 编程指南](https://www.inf.ed.ac.uk/teaching/courses/ppls/TBBtutorial.pdf)
- [CMake “菜谱”](https://www.bookstack.cn/read/CMake-Cookbook/README.md)
- [CMake 官方文档](https://cmake.org/cmake/help/latest/)
- [Git 官方文档](https://git-scm.com/doc)
- [GitHub 官方文档](https://docs.github.com/en)
- [实用网站 CppInsights 解构 C++ 语法糖](https://cppinsights.io)
- [实用网站 GodBolt 查看不同编译器生成的汇编](http://godbolt.org)


创作不易,小小的支持一下吧!

  • 14
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码力码力我爱你

创作不易,小小的支持一下吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值