mirror of
https://github.com/changkun/modern-cpp-tutorial.git
synced 2025-12-17 04:34:40 +03:00
see #2: update exercises and maintains of content
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
|
||||
## 随书习题
|
||||
|
||||
本书每章最后还加入了少量难度极小的习题,仅用于检验你是否能混合运用当前章节中的知识点。你可以在[这里](exercises)找到习题的答案,文件夹名称为章节序号。
|
||||
本书每章最后还加入了少量难度极小的习题,仅用于检验你是否能混合运用当前章节中的知识点。你可以在[这里](./exercises)找到习题的答案,文件夹名称为章节序号。
|
||||
|
||||
## 本书网站
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ Each chapter of this book has a lot of code. If you encounter problems when writ
|
||||
|
||||
## Exercises
|
||||
|
||||
There are few exercises At the end of each chapter of the book. It is for testing whether you can use the knowledge points in the current chapter. You can find the possible answer to the problem from [here](./exercise). The folder name is the chapter number.
|
||||
There are few exercises At the end of each chapter of the book. It is for testing whether you can use the knowledge points in the current chapter. You can find the possible answer to the problem from [here](./exercises). The folder name is the chapter number.
|
||||
|
||||
## Website
|
||||
|
||||
|
||||
@@ -76,13 +76,14 @@
|
||||
+ `std::regex`
|
||||
+ `std::regex_match`
|
||||
+ `std::match_results`
|
||||
- [**Chapter 07 Sandard Library: Threads and Concurrency**](./07-thread.md)
|
||||
- [**Chapter 07 Parallelism and Concurrency**](./07-thread.md)
|
||||
+ 7.1 `std::thread`
|
||||
+ 7.2 `std::mutex` and `std::unique_lock`
|
||||
+ 7.3 `std::future` and `std::packaged_task`
|
||||
+ 7.4 `std::condition_variable`
|
||||
+ 7.5 `std::atomic` and memory order
|
||||
+ 7.6 Transactional memory
|
||||
+ 7.7 Coroutine
|
||||
- [**Chapter 08 Sandard Library: File System**](./08-filesystem.md)
|
||||
+ 8.1 Documents and links
|
||||
+ 8.2 `std::filesystem`
|
||||
|
||||
@@ -134,7 +134,6 @@ bar.txt sub-match[1]: bar
|
||||
|
||||
1. [知乎『如何评价 GCC 的 C++11 正则表达式?』中原库作者 Tim Shen 的回答](http://zhihu.com/question/23070203/answer/84248248)
|
||||
2. [正则表达式库文档](http://en.cppreference.com/w/cpp/regex)
|
||||
3. [C++ 开发 Web 服务框架](https://www.shiyanlou.com/courses/568)
|
||||
|
||||
## 许可
|
||||
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
---
|
||||
title: 第 7 章 标准库:线程与并发
|
||||
title: 第 7 章 并行与并发
|
||||
type: book-zh-cn
|
||||
order: 7
|
||||
---
|
||||
|
||||
# 第 7 章 标准库:线程与并发
|
||||
# 第 7 章 并行与并发
|
||||
|
||||
> 内容修订中
|
||||
|
||||
[TOC]
|
||||
|
||||
## 7.1 std::thread
|
||||
## 7.1 线程与并行
|
||||
|
||||
### std::thread
|
||||
|
||||
`std::thread` 用于创建一个执行的线程实例,所以它是一切并发编程的基础,使用时需要包含 `<thread>` 头文件,它提供了很多基本的线程操作,例如`get_id()`来获取所创建线程的线程 ID,例如使用 `join()` 来加入一个线程等等,例如:
|
||||
|
||||
@@ -179,7 +181,21 @@ consumer.join();
|
||||
|
||||
C++11 语言层提供了并发编程的相关支持,本节简单的介绍了 `std::thread`/`std::mutex`/`std::future` 这些并发编程中不可回避的重要工具。
|
||||
|
||||
> 本节提到的内容足以让我们使用不超过 100 行代码编写一个简单的线程池库,请参考习题 TODO
|
||||
## 习题
|
||||
|
||||
1. 请编写一个线程池,提供如下功能:
|
||||
|
||||
```cpp
|
||||
ThreadPool p(4); // 指定四个工作线程
|
||||
|
||||
// 将任务在池中入队,并返回一个 std::future
|
||||
auto f = pool.enqueue([](int life) {
|
||||
return meaning;
|
||||
}, 42);
|
||||
|
||||
// 从 future 中获得执行结果
|
||||
std::cout << f.get() << std::endl;
|
||||
```
|
||||
|
||||
[返回目录](./toc.md) | [上一章](./06-regex.md) | [下一章 标准库:文件系统](./08-filesystem.md)
|
||||
|
||||
@@ -187,8 +203,6 @@ C++11 语言层提供了并发编程的相关支持,本节简单的介绍了 `
|
||||
|
||||
1. [C++ 并发编程\(中文版\)](https://www.gitbook.com/book/chenxiaowei/cpp_concurrency_in_action/details)
|
||||
2. [线程支持库文档](http://en.cppreference.com/w/cpp/thread)
|
||||
3. [100 行 C++ 代码实现线程池](https://www.shiyanlou.com/teacher/courses/565)
|
||||
|
||||
|
||||
## 许可
|
||||
|
||||
|
||||
@@ -76,13 +76,14 @@
|
||||
+ `std::regex`
|
||||
+ `std::regex_match`
|
||||
+ `std::match_results`
|
||||
- [**第 7 章 标准库: 线程与并发**](./07-thread.md)
|
||||
- [**第 7 章 并行与并发**](./07-thread.md)
|
||||
+ 7.1 `std::thread`
|
||||
+ 7.2 `std::mutex` 和 `std::unique_lock`
|
||||
+ 7.3 `std::future` 和 `std::packaged_task`
|
||||
+ 7.4 `std::condition_variable`
|
||||
+ 7.5 `std::atomic` 与内存顺序
|
||||
+ 7.6 事务内存
|
||||
+ 7.7 协程
|
||||
- [**第 8 章 标准库: 文件系统**](./08-filesystem.md)
|
||||
+ 8.1 文档与链接
|
||||
+ 8.2 `std::filesystem`
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
//
|
||||
// fold.expression.cpp
|
||||
//
|
||||
// exercise solution - chapter 2
|
||||
// modern cpp tutorial
|
||||
//
|
||||
// created by changkun at changkun.de
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
template<typename ... T>
|
||||
auto average(T ... t) {
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
//
|
||||
// structured.binding.cpp
|
||||
//
|
||||
// exercise solution - chapter 2
|
||||
// modern cpp tutorial
|
||||
//
|
||||
// created by changkun at changkun.de
|
||||
//
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
//
|
||||
// variadic.template.parameter.pack.cpp
|
||||
//
|
||||
// exercise solution - chapter 2
|
||||
// modern cpp tutorial
|
||||
//
|
||||
// created by changkun at changkun.de
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Makefile
|
||||
# web_server
|
||||
#
|
||||
# created by changkun at labex.io
|
||||
# created by changkun at changkun.de/modern-cpp
|
||||
#
|
||||
|
||||
CXX = g++
|
||||
@@ -15,15 +15,16 @@ SOURCE_HTTPS = main.https.cpp
|
||||
OBJECTS_HTTP = main.http.o
|
||||
OBJECTS_HTTPS = main.https.o
|
||||
|
||||
LDFLAGS_COMMON = -std=c++11 -O3 -pthread -lboost_system
|
||||
LDFLAGS_COMMON = -std=c++2a -O3 -pthread -lboost_system
|
||||
LDFLAGS_HTTP =
|
||||
LDFLAGS_HTTPS = -lssl -lcrypto
|
||||
|
||||
LPATH_COMMON = -I/usr/include/boost
|
||||
LPATH_HTTP =
|
||||
LPATH_HTTPS = -I/usr/include/openssl
|
||||
LPATH_HTTPS = -I/usr/local/opt/openssl/include
|
||||
|
||||
LLIB_COMMON = -L/usr/lib
|
||||
LLIB_HTTPS = -L/usr/local/opt/openssl/lib
|
||||
|
||||
all:
|
||||
make http
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace LabexWeb;
|
||||
using namespace Web;
|
||||
|
||||
template<typename SERVER_TYPE>
|
||||
void start_server(SERVER_TYPE &server) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "server.http.hpp"
|
||||
#include "handler.hpp"
|
||||
|
||||
using namespace LabexWeb;
|
||||
using namespace Web;
|
||||
|
||||
int main() {
|
||||
// HTTP server runs in port 12345 HTTP, enable 4 threads
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <iostream>
|
||||
#include "server.https.hpp"
|
||||
#include "handler.hpp"
|
||||
using namespace LabexWeb;
|
||||
using namespace Web;
|
||||
|
||||
int main() {
|
||||
// HTTPS server runs in port 12345, enable 4 threads
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
|
||||
namespace LabexWeb {
|
||||
namespace Web {
|
||||
struct Request {
|
||||
// request method, POST, GET; path; HTTP version
|
||||
std::string method, path, http_version;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "server.base.hpp"
|
||||
|
||||
namespace LabexWeb {
|
||||
namespace Web {
|
||||
typedef boost::asio::ip::tcp::socket HTTP;
|
||||
template<>
|
||||
class Server<HTTP> : public ServerBase<HTTP> {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "server.http.hpp"
|
||||
#include <boost/asio/ssl.hpp>
|
||||
|
||||
namespace LabexWeb {
|
||||
namespace Web {
|
||||
|
||||
// define HTTPS type
|
||||
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> HTTPS;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>LabEx Web Server Test</title>
|
||||
<title>Web Server Test</title>
|
||||
</head>
|
||||
<body>
|
||||
Hello world in index.html.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>LabEx Web Server Test</title>
|
||||
<title>Web Server Test</title>
|
||||
</head>
|
||||
<body>
|
||||
Hello world in test.html.
|
||||
|
||||
16
exercises/7/Makefile
Normal file
16
exercises/7/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Makefile
|
||||
#
|
||||
# exercise solution - chapter 7
|
||||
# modern cpp tutorial
|
||||
#
|
||||
# created by changkun at changkun.de/modern-cpp
|
||||
#
|
||||
|
||||
all: $(patsubst %.cpp, %.out, $(wildcard *.cpp))
|
||||
|
||||
%.out: %.cpp Makefile
|
||||
clang++ $< -o $@ -std=c++2a -pedantic
|
||||
|
||||
clean:
|
||||
rm *.out
|
||||
@@ -1,3 +1,12 @@
|
||||
//
|
||||
// main.cpp
|
||||
//
|
||||
// exercise solution - chapter 7
|
||||
// modern cpp tutorial
|
||||
//
|
||||
// created by changkun at changkun.de/modern-cpp
|
||||
//
|
||||
|
||||
#include <iostream> // std::cout, std::endl
|
||||
|
||||
#include <vector> // std::vector
|
||||
@@ -6,7 +15,7 @@
|
||||
#include <thread> // std::this_thread::sleep_for
|
||||
#include <chrono> // std::chrono::seconds
|
||||
|
||||
#include "ThreadPool.hpp"
|
||||
#include "thread_pool.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
//
|
||||
// thread_pool.hpp
|
||||
//
|
||||
// exercise solution - chapter 7
|
||||
// modern cpp tutorial
|
||||
//
|
||||
// created by changkun at changkun.de/modern-cpp
|
||||
//
|
||||
|
||||
#ifndef THREAD_POOL_H
|
||||
#define THREAD_POOL_H
|
||||
|
||||
@@ -22,8 +31,7 @@ public:
|
||||
|
||||
// enqueue new thread task
|
||||
template<class F, class... Args>
|
||||
auto enqueue(F&& f, Args&&... args)
|
||||
-> std::future<typename std::result_of<F(Args...)>::type>;
|
||||
decltype(auto) enqueue(F&& f, Args&&... args);
|
||||
|
||||
// destroy thread pool and all created threads
|
||||
~ThreadPool();
|
||||
@@ -45,21 +53,15 @@ private:
|
||||
};
|
||||
|
||||
// constructor initialize a fixed size of worker
|
||||
inline ThreadPool::ThreadPool(size_t threads): stop(false)
|
||||
{
|
||||
inline ThreadPool::ThreadPool(size_t threads): stop(false) {
|
||||
// initialize worker
|
||||
for(size_t i = 0;i<threads;++i)
|
||||
// std::vector::emplace_back :
|
||||
// append to the end of vector container
|
||||
// this element will be constructed at the end of container, without copy and move behavior
|
||||
workers.emplace_back(
|
||||
// the lambda express capture this, i.e. the instance of thread pool
|
||||
[this]
|
||||
{
|
||||
workers.emplace_back([this] { // the lambda express capture this, i.e. the instance of thread pool
|
||||
// avoid fake awake
|
||||
for(;;)
|
||||
{
|
||||
|
||||
for(;;) {
|
||||
// define function task container, return type is void
|
||||
std::function<void()> task;
|
||||
|
||||
@@ -91,9 +93,7 @@ inline ThreadPool::ThreadPool(size_t threads): stop(false)
|
||||
// Enqueue a new thread
|
||||
// use variadic templates and tail return type
|
||||
template<class F, class... Args>
|
||||
auto ThreadPool::enqueue(F&& f, Args&&... args)
|
||||
-> std::future<typename std::result_of<F(Args...)>::type>
|
||||
{
|
||||
decltype(auto) ThreadPool::enqueue(F&& f, Args&&... args) {
|
||||
// deduce return type
|
||||
using return_type = typename std::result_of<F(Args...)>::type;
|
||||
|
||||
@@ -5385,12 +5385,12 @@ S
|
||||
endstream
|
||||
endobj
|
||||
16 0 obj
|
||||
<</Filter/FlateDecode/Length 611>>
|
||||
<</Filter/FlateDecode/Length 614>>
|
||||
stream
|
||||
xÚ}UËŽÛ0¼÷+ôÖJEÉ@àCÑÚÛ¹=4q²§E±ýÿCI“´Ýìf‘,>†Ã¡^B‰94<08>ÆØÇp~<1F>ááK¹EÈÃñrJ±C†8fÇùç!%ø<>Rí}ˆô¿ŒÛšP×tJ©<4A>ÓPZeïšRÂÙwÄöåÊø›ÂØÙƒ¦_ÇïŒBÎq¬BdÛ0”{Û’ ù,¡yÍ QÏ–
|
||||
ÈÓ¶«êƒ¸N8MËûûqا뚤h‡WÂGt@±bô©:lQ¼Hh(pÐ8'6•,é† | ||||