-
背景 每一个cpp expression都有一个type 和 value category 属性 前者大家都比较了解,但是后者却常常被忽视 Value Categories in the c language cpp是由c语言发展而来,因此这里先介绍c 语言中的value category c语言只有简单的lvalue和rvalue两种 lvalue lvalue的"l"表示"left",表示lvalue可以出现在assigment operator的左边 更准确的说 Tip "lvalue is a value refer to an object" "an …
Read More -
概述 std::shared_ptr是智能指针的一种,在modern c++中被广泛使用(甚至滥用) 虽然天天使用,但是有些细节还不是100%清楚,因此来整理一下 为了方便表述,下文只写shared_ptr,不在写std的namespace. 组成 shared_ptr的实现中,成员通常由两部分组成。一个是所涵盖对象的指针,一个是control block 的指针 control block Tip 最重要的是,control block是 dynamically-allocated 的 (校招的时候某次面试,让我手写shared_ptr的实现,当时被多个object如何共享引用计数卡住了。。主要就是没意识到control …
Read More -
背景 一种很常见的背景是,需要表示未知类型的数据。 比如可能是用户提供的数据,比如是一个Cache的实现, value想支持任意类型的数据 对于这种场景,c语言的出身的开发者通常会使用void*来实现 1struct day { 2 // ...things... 3 void* user_data; 4}; 5 6struct month { 7 std::vector<day> days; 8 void* user_data; 9}; 10 了解cpp11的开发者可能会使用std::shared_ptr<void> 来实现 1struct day { 2 // ...things... 3 …
Read More -
把std::async,std::packaged_task,std::promise三个放在一起来说,是因为他们都可以返回一个std::future对象.简单来说,当某个线程需要等待一个特定的一次性事件(one-off event),它可以用一个"future"来表示这个事件. std::async 有的时候可能你需要做一个花费事件比较长的计算,但是计算结果不是立刻需要.这个时候就可以用一个新的线程来做这个计算.这里比较关键的问题是如何将在新线程进行计算的结果传回到当前线程,因为std::thread并没有提供一个类似的机制. 这个时候就需要std::async登场了. 1 2 #include …
Read More -
condition_variable 类是同步原语,能用于阻塞一个线程,或同时阻塞多个线程,直至另一线程修改共享变量(条件)并通知 condition_variable 。 用人话来说,condition_variable,也就是条件变量,是线程间通信的一种方式。 线程之间在很多时候需要通信,比如经典的生产者消费者问题 一个比较naive的方案是,用mutex来保护一个flag,然后另一线程不停得check这个flag的状态是否改变。以及在这个方案上的改进:让另一个线程check之后,可以先睡一段时间。 但是这两种方法都不够好。第一种不好的原因当然是不停得check,肯定会耗费大量的资源。而第二种,由于没办法准确估计要休眠的时间,因 …
Read More -
多线程保护数据时,一种较为特殊的情况是只需要保护资源的初始化。 资源初始化一般遵循"lazy initialization"的原则,也就是在用到该资源最近的地方再初始化。 比较容易想到的办法是用std::mutex,将资源初始化的地方锁起来,如下: 1 std::shared_ptr<some_resource> resource_ptr; 2 std::mutex resource_mutex; 3 void foo() 4 { 5 std::unique_lock<std::mutex> lk(resource_mutex); 6 if(!resource_ptr) 7 { 8 …
Read More -
起因是在看《CplusplusConcurrencyInAction_PracticalMultithreading》的时候,里面讲到初始化std::thread的时候,如果thread funtion的参数列表中有引用,需要传入std::ref才可以得到符合预期的结果。 查阅发现std::ref是用来生成std::reference_wrapper。 按照 cppreference 上的话来说 `std::reference_wrapper` 是包装引用于可复制、可赋值对象的类模板。它常用作将容器存储入无法正常保有引用的标准容器( …
Read More -
用人话就是,主线程传给附属线程一个promise Object,然后主线程想要获取附属线程set给promise Object的值(也就是该线程返回的某个结果),需要通过主线程中的promise object 得到对应的future object(每个promise 对应一个 future),然后调用future 的get方法。如果附属线程没有执行作为参数传入的promise的set方法去返回结果,那么程序就会block住。 1 /* *********************************************** 2Author :111qqz 3mail: renkuanze@sensetime.com …
Read More -
C++11 std::function 是一种通用、多态的函数封装,它的实例可以对任何可 以调用的目标实体进行存储、复制和调用操作 见下面的例子 1 /* *********************************************** 2Author :111qqz 3mail: renkuanze@sensetime.com 4Created Time :2018年07月19日 星期四 17时41分00秒 5File Name :bind.cpp 6************************************************ */ 7 #include <functional>8 …
Read More -
以前用的办法太老土啦 看到一个since C++11的方法,我觉得比较优雅 1 #include <iostream>2 #include <chrono>3 //#include <ratio> 4 #include <thread>5 6 void f() 7 { 8 std::this_thread::sleep_for(std::chrono::seconds(1)); 9 } 10 11 int main() 12 { 13 auto t1 = std::chrono::high_resolution_clock::now(); 14 f(); 15 auto t2 = …
Read More