Skip to content

Commit

Permalink
ch14: update
Browse files Browse the repository at this point in the history
  • Loading branch information
gav2xlin committed Jan 29, 2025
1 parent 7e610a3 commit abe4666
Show file tree
Hide file tree
Showing 29 changed files with 744 additions and 17 deletions.
4 changes: 2 additions & 2 deletions Chapter01/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.16)
cmake_minimum_required(VERSION 3.28)

project(
ch01
Chapter01
VERSION 0.0.1
LANGUAGES CXX)

Expand Down
2 changes: 1 addition & 1 deletion Chapter01/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Software Architecture with C++, Second Edition, Published by Packt

Install the following software:

- CMake 3.16
- CMake 3.28
- GCC 14

### Building
Expand Down
4 changes: 2 additions & 2 deletions Chapter02/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.16)
cmake_minimum_required(VERSION 3.28)

project(
ch02
Chapter02
VERSION 0.0.1
LANGUAGES CXX)

Expand Down
2 changes: 1 addition & 1 deletion Chapter02/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Software Architecture with C++, Second Edition, Published by Packt

Install the following software:

- CMake 3.16
- CMake 3.28
- Conan 2.11.0
- GCC 14

Expand Down
2 changes: 1 addition & 1 deletion Chapter03/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.16)
cmake_minimum_required(VERSION 3.28)

project(
"Breathe Demo"
Expand Down
4 changes: 2 additions & 2 deletions Chapter03/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ This README file should be included in the docs as the main page.

Install the following software:

- CMake
- A C++ compiler
- CMake 3.28
- GCC 14
- Sphinx
- ReadTheDocs Sphinx theme
- Breathe
Expand Down
4 changes: 2 additions & 2 deletions Chapter06/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16)
cmake_minimum_required(VERSION 3.28)

project(ch06 LANGUAGES CXX)
project(Chapter06 LANGUAGES CXX)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
Expand Down
2 changes: 1 addition & 1 deletion Chapter06/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Software Architecture with C++, Second Edition, Published by Packt

Install the following software:

- CMake 3.16
- CMake 3.28
- Conan 2.11.0
- GCC 14

Expand Down
4 changes: 2 additions & 2 deletions Chapter10/customer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ To run tests from each of the projects, cd into their respective build directory

### Troubleshooting

If you see this, edit `~/.conan2/profiles/default` and set `compiler.cppstd=gnu20` (or higher):
If you see this error, edit `~/.conan2/profiles/default` and set `compiler.cppstd=gnu20` (or higher):

```
boost-ext-ut/2.1.0: Invalid: Current cppstd (gnu17) is lower than the required C++ standard (20).
boost-ext-ut/*: Invalid: Current cppstd (gnu17) is lower than the required C++ standard (20).
```
2 changes: 2 additions & 0 deletions Chapter13/customer/src/customer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ target_compile_features(customer PRIVATE cxx_std_17)
target_link_libraries(customer PRIVATE libcustomer)
set_target_properties(customer PROPERTIES CXX_EXTENSIONS OFF)
target_compile_options(customer PRIVATE ${BASE_COMPILE_FLAGS})
# to disable min() and max() macros in windows.h
target_compile_definitions(customer PRIVATE NOMINMAX)

file(GLOB SCP_LIST ${CMAKE_CURRENT_SOURCE_DIR}/views/*.csp)
foreach(cspFile ${SCP_LIST})
Expand Down
2 changes: 1 addition & 1 deletion Chapter13/mobile_app/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.15)
cmake_minimum_required(VERSION 3.28)

project(
MobileApp
Expand Down
2 changes: 0 additions & 2 deletions Chapter13/mobile_app/conanfile.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
[requires]
catch2/3.7.1
trompeloeil/49
ms-gsl/4.1.0

[generators]
Expand Down
29 changes: 29 additions & 0 deletions Chapter14/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.28)

project(
Chapter14
VERSION 0.0.1
LANGUAGES CXX)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)

list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")
find_package(benchmark REQUIRED)
find_package(nanobench CONFIG REQUIRED)
find_package(doctest REQUIRED)

if(NOT APPLE)
find_package(libcoro CONFIG REQUIRED)
endif()

find_package(Boost REQUIRED)

if(NOT MSVC)
find_package(coost CONFIG REQUIRED)
endif()

add_subdirectory(coroutines)
add_subdirectory(microbenchmarking/benchmark)
add_subdirectory(microbenchmarking/nanobench)
80 changes: 80 additions & 0 deletions Chapter14/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Software Architecture with C++, Second Edition

Software Architecture with C++, Second Edition, Published by Packt

## Chapter 14: Performance

### Prerequisites

Install the following software:

- CMake 3.28
- Conan 2.11.0
- GCC 14

Assuming you're on Linux or using WSL, configure a local Conan profile and remotes by running:

```bash
rm -rf ./build/
conan profile detect --name ./build/conan_profile
```

Make sure that the profile section `[settings]` contains:

```text
arch=x86_64
compiler=gcc
compiler.cppstd=gnu20
compiler.libcxx=libstdc++11
compiler.version=14
os=Linux
```

### Building

To build the project, configure the Conan profile as described above, cd to its directory, and then run:

```bash
cd build
conan install .. --build=missing -s build_type=Release -pr:a=./conan_profile -of .
cmake .. -DCMAKE_BUILD_TYPE=Release # build type must match Conan's
cmake --build .
```

If GCC 14 is not your default compiler, you can tell CMake to use it with the `CMAKE_CXX_COMPILER` flag:

```bash
cd build
conan install .. --build=missing -s build_type=Release -pr:a=./conan_profile -of .
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=`which g++-14` # build type must match Conan's
cmake --build .
```

To pass the settings directly without a Conan profile, use the command line option `--settings:all` or `-s:a`, and the keys `arch`, `build_type`, `compiler`, `compiler.cppstd`, `compiler.libcxx`, `compiler.version`, `os`:

```bash
rm -rf ./build/ && mkdir build && cd build
conan install .. --build=missing -s:a build_type=Release -s:a compiler=gcc -of .
cmake .. -DCMAKE_BUILD_TYPE=Release # build type must match Conan's
cmake --build .
```

To apply Conan dependency as a CMake Dependency Provider, clone this Git repository and then run the next command:

```bash
rm -rf ./build/cmake-conan
git clone https://github.com/conan-io/cmake-conan.git build/cmake-conan
```

```bash
cmake -S . -B build -DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=./build/cmake-conan/conan_provider.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build build
```

### Troubleshooting

If you see this error, edit `~/.conan2/profiles/default` and set `compiler.cppstd=gnu20` (or higher):

```
libcoro/*: Invalid: Current cppstd (gnu17) is lower than the required C++ standard (20).
```
20 changes: 20 additions & 0 deletions Chapter14/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from conan import ConanFile
from conan.tools.apple import is_apple_os
from conan.tools.microsoft import is_msvc

class Pkg(ConanFile):
settings = "os", "arch", "compiler", "build_type"
generators = "CMakeDeps"

def requirements(self):
self.requires("benchmark/1.9.1")
self.requires("nanobench/4.3.11")
self.requires("doctest/2.4.11")
if not is_apple_os(self):
self.requires("libcoro/0.12.1")
self.requires("boost/1.86.0")
if not is_msvc(self):
self.requires("coost/3.0.2")

def build_requirements(self):
pass
15 changes: 15 additions & 0 deletions Chapter14/coroutines/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
if(NOT APPLE)
add_executable(coroutines_1 main_1.cpp)
target_link_libraries(coroutines_1 PRIVATE libcoro::libcoro)
target_compile_features(coroutines_1 PRIVATE cxx_std_23)
endif()

add_executable(coroutines_2 main_2.cpp)
target_link_libraries(coroutines_2 PRIVATE Boost::cobalt)
target_compile_features(coroutines_2 PRIVATE cxx_std_23)

if(NOT MSVC)
add_executable(coroutines_3 main_3.cpp)
target_link_libraries(coroutines_3 PRIVATE coost::co)
target_compile_features(coroutines_3 PRIVATE cxx_std_23)
endif()
70 changes: 70 additions & 0 deletions Chapter14/coroutines/main_1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <chrono>
#include <coro/coro.hpp>
#include <print>
#include <random>
#include <thread>
#include <vector>

inline constexpr auto WORK_ITEMS = 5;

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> distrib(0, 800);

coro::task<> fill_number(int i, std::vector<int> &ints,
coro::thread_pool &thread_pool, coro::mutex &mutex) {
co_await thread_pool.schedule();

std::println("Thread {}: producing {}", std::this_thread::get_id(), i);
std::this_thread::sleep_for(std::chrono::milliseconds(distrib(gen)));

{
// remember to co_await!
auto lock = co_await mutex.lock();
ints.emplace_back(i);
}

std::println("Thread {}: produced {}", std::this_thread::get_id(), i);
co_return;
}

coro::task<std::vector<int>> do_routine_work(coro::thread_pool &thread_pool) {
auto mutex = coro::mutex{};
auto ints = std::vector<int>{};
ints.reserve(WORK_ITEMS);

std::println("Thread {}: passing execution to the pool",
std::this_thread::get_id());

co_await thread_pool.schedule();
std::println("Thread {}: running first pooled job",
std::this_thread::get_id());

std::vector<coro::task<>> tasks;
tasks.reserve(WORK_ITEMS);

for (int i = 0; i < WORK_ITEMS; ++i) {
tasks.emplace_back(fill_number(i, ints, thread_pool, mutex));
}

co_await coro::when_all(std::move(tasks));

co_return ints;
}

int main() {
auto thread_pool = coro::thread_pool{{.thread_count = 3}};

std::println("Thread {}: preparing work", std::this_thread::get_id());
auto work = do_routine_work(thread_pool);

std::println("Thread {}: starting work", std::this_thread::get_id());
const auto ints = coro::sync_wait(work);

std::print("Thread {}: work done.\nProduced ints are: ",
std::this_thread::get_id());
for (auto i : ints) {
std::print("{}, ", i);
}
std::println();
}
Loading

0 comments on commit abe4666

Please sign in to comment.