├── CMakeLists.txt ├── Chapter02 ├── CMakeLists.txt ├── scratchpad.c └── scratchpad.cpp ├── Chapter03 ├── CMakeLists.txt └── scratchpad.cpp ├── Chapter04 ├── CMakeLists.txt └── scratchpad.cpp ├── Chapter05 ├── CMakeLists.txt └── scratchpad.cpp ├── Chapter06 ├── CMakeLists.txt ├── example1.cpp ├── example2.cpp └── scratchpad.cpp ├── Chapter07 ├── CMakeLists.txt └── scratchpad.cpp ├── Chapter08 ├── CMakeLists.txt ├── example1.cpp ├── example2.cpp ├── example3.cpp └── scratchpad.cpp ├── Chapter09 ├── CMakeLists.txt ├── example1.cpp ├── example2.cpp ├── example3.cpp ├── example4.cpp ├── example5.cpp ├── example6.cpp └── example7.cpp ├── Chapter10 ├── CMakeLists.txt ├── example1.cpp ├── example2.cpp ├── example3.cpp ├── example4.cpp └── example5.cpp ├── Chapter11 ├── CMakeLists.txt ├── example1.cpp ├── example2.cpp └── scratchpad.cpp ├── Chapter12 ├── CMakeLists.txt ├── example1.cpp ├── example2.cpp ├── example3.cpp └── scratchpad.cpp ├── Chapter13 ├── CMakeLists.txt ├── example1.cpp └── scratchpad.cpp ├── LICENSE └── README.md /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(book) 28 | 29 | include(ExternalProject) 30 | 31 | # ------------------------------------------------------------------------------ 32 | # Helper 33 | # ------------------------------------------------------------------------------ 34 | 35 | function(add_chapter name) 36 | ExternalProject_Add( 37 | ${name} 38 | PREFIX ${CMAKE_BINARY_DIR}/extras/${name}/prefix 39 | TMP_DIR ${CMAKE_BINARY_DIR}/extras/${name}/tmp 40 | STAMP_DIR ${CMAKE_BINARY_DIR}/extras/${name}/stamp 41 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/extras/${name}/download 42 | SOURCE_DIR ${CMAKE_SOURCE_DIR}/${name} 43 | BINARY_DIR ${CMAKE_BINARY_DIR}/extras/${name}/build 44 | INSTALL_COMMAND "" 45 | ) 46 | endfunction(add_chapter) 47 | 48 | # ------------------------------------------------------------------------------ 49 | # Chapters 50 | # ------------------------------------------------------------------------------ 51 | 52 | add_chapter(Chapter02) 53 | add_chapter(Chapter03) 54 | add_chapter(Chapter04) 55 | add_chapter(Chapter05) 56 | add_chapter(Chapter06) 57 | add_chapter(Chapter07) 58 | add_chapter(Chapter08) 59 | add_chapter(Chapter09) 60 | add_chapter(Chapter10) 61 | add_chapter(Chapter11) 62 | add_chapter(Chapter12) 63 | add_chapter(Chapter13) 64 | -------------------------------------------------------------------------------- /Chapter02/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter02) 28 | 29 | set(CMAKE_CXX_STANDARD 17) 30 | 31 | # ------------------------------------------------------------------------------ 32 | # Snippets 33 | # ------------------------------------------------------------------------------ 34 | 35 | function(snippet_c number) 36 | add_executable(snippet_c${number} scratchpad.c) 37 | target_compile_definitions(snippet_c${number} PRIVATE SNIPPET${number}) 38 | endfunction(snippet_c) 39 | 40 | function(snippet_cpp number) 41 | add_executable(snippet_cpp${number} scratchpad.cpp) 42 | target_compile_definitions(snippet_cpp${number} PRIVATE SNIPPET${number}) 43 | endfunction(snippet_cpp) 44 | 45 | snippet_c(01) 46 | snippet_c(02) 47 | snippet_c(03) 48 | snippet_c(04) 49 | snippet_c(05) 50 | snippet_c(06) 51 | snippet_c(07) 52 | snippet_cpp(01) 53 | snippet_cpp(02) 54 | snippet_cpp(03) 55 | snippet_cpp(04) 56 | snippet_cpp(05) 57 | snippet_cpp(06) 58 | -------------------------------------------------------------------------------- /Chapter02/scratchpad.c: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #if SNIPPET01 23 | 24 | #include 25 | 26 | int main(void) 27 | { 28 | printf("Hello World\n"); 29 | } 30 | 31 | // > gcc scratchpad.c; ./a.out 32 | // Hello World 33 | 34 | #endif 35 | 36 | #if SNIPPET02 37 | 38 | int test(void) 39 | { 40 | return 0; 41 | } 42 | 43 | int main(void) 44 | { 45 | return test(); 46 | } 47 | 48 | // > gcc scratchpad.c; ./a.out 49 | 50 | #endif 51 | 52 | #if SNIPPET03 53 | 54 | int test(void) 55 | { 56 | return 0; 57 | } 58 | 59 | int main(void) 60 | { 61 | return test(); 62 | } 63 | 64 | // > gcc scratchpad.c; ./a.out 65 | 66 | #endif 67 | 68 | #if SNIPPET04 69 | 70 | int main(void) 71 | { 72 | int i; 73 | int *p = &i; 74 | } 75 | 76 | // > gcc scratchpad.c; ./a.out 77 | 78 | #endif 79 | 80 | #if SNIPPET05 81 | 82 | int main(void) 83 | { 84 | int i; 85 | void *p = &i; 86 | 87 | int *int_p = p; 88 | float *float_p = p; 89 | } 90 | 91 | // > gcc scratchpad.c; ./a.out 92 | 93 | #endif 94 | 95 | #if SNIPPET06 96 | 97 | #include 98 | 99 | int main(void) 100 | { 101 | int i = 42; 102 | int *p = &i; 103 | 104 | if (p) { 105 | printf("The answer is: %d\n", *p); 106 | } 107 | } 108 | 109 | // > gcc scratchpad.c; ./a.out 110 | // The answer is: 42 111 | 112 | #endif 113 | 114 | #if SNIPPET07 115 | 116 | #include 117 | 118 | int main(void) 119 | { 120 | int i[2] = {42, 43}; 121 | int *p = i; 122 | 123 | if (p) { 124 | printf("The answer is: %d and %d\n", i[0], *(p + 0)); 125 | printf("The answer is: %d and %d\n", i[1], *(p + 1)); 126 | } 127 | } 128 | 129 | // > gcc scratchpad.c; ./a.out 130 | // The answer is: 42 and 42 131 | // The answer is: 43 and 43 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /Chapter02/scratchpad.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #if SNIPPET01 23 | 24 | #include 25 | 26 | int main(void) 27 | { 28 | std::cout << "Hello World\n"; 29 | } 30 | 31 | // > g++ scratchpad.cpp; ./a.out 32 | // Hello World 33 | 34 | #endif 35 | 36 | #if SNIPPET02 37 | 38 | void test(void) {} 39 | void test(bool b) {} 40 | 41 | int main(void) 42 | { 43 | test(); 44 | test(false); 45 | } 46 | 47 | // > g++ scratchpad.cpp; ./a.out 48 | 49 | #endif 50 | 51 | #if SNIPPET03 52 | 53 | #include 54 | 55 | struct mystruct { 56 | int data1{42}; 57 | int data2{42}; 58 | }; 59 | 60 | int main(void) 61 | { 62 | mystruct s; 63 | std::cout << s.data1 << '\n'; 64 | } 65 | 66 | // > g++ scratchpad.cpp; ./a.out 67 | // 42 68 | 69 | #endif 70 | 71 | #if SNIPPET04 72 | 73 | struct mystruct { 74 | int data1{}; 75 | int data2{}; 76 | int data3{}; 77 | int data4{}; 78 | int data5{}; 79 | int data6{}; 80 | int data7{}; 81 | int data8{}; 82 | }; 83 | 84 | void test(mystruct *s) 85 | { 86 | } 87 | 88 | int main(void) 89 | { 90 | mystruct s; 91 | test(&s); 92 | } 93 | 94 | // > g++ scratchpad.cpp; ./a.out 95 | 96 | #endif 97 | 98 | #if SNIPPET05 99 | 100 | struct mystruct { 101 | int data1{}; 102 | int data2{}; 103 | int data3{}; 104 | int data4{}; 105 | int data5{}; 106 | int data6{}; 107 | int data7{}; 108 | int data8{}; 109 | }; 110 | 111 | void test(mystruct &s) 112 | { 113 | } 114 | 115 | int main(void) 116 | { 117 | mystruct s; 118 | test(s); 119 | } 120 | 121 | // > g++ scratchpad.cpp; ./a.out 122 | 123 | #endif 124 | 125 | #if SNIPPET06 126 | 127 | #include 128 | 129 | int main() 130 | { 131 | void *ptr; 132 | 133 | if (posix_memalign(&ptr, 0x1000, 42 * sizeof(int))) { 134 | std::clog << "ERROR: unable to allocate aligned memory\n"; 135 | ::exit(EXIT_FAILURE); 136 | } 137 | 138 | std::cout << ptr << '\n'; 139 | free(ptr); 140 | } 141 | 142 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 143 | // 0x55c5d31d1000 144 | 145 | #endif 146 | 147 | -------------------------------------------------------------------------------- /Chapter03/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter03) 28 | 29 | set(CMAKE_CXX_STANDARD 17) 30 | 31 | # ------------------------------------------------------------------------------ 32 | # Snippets 33 | # ------------------------------------------------------------------------------ 34 | 35 | function(snippet number) 36 | add_executable(snippet${number} scratchpad.cpp) 37 | target_compile_definitions(snippet${number} PRIVATE SNIPPET${number}) 38 | endfunction(snippet) 39 | 40 | snippet(01) 41 | snippet(02) 42 | snippet(03) 43 | snippet(04) 44 | snippet(05) 45 | snippet(06) 46 | snippet(07) 47 | snippet(08) 48 | snippet(09) 49 | snippet(10) 50 | snippet(11) 51 | snippet(12) 52 | snippet(13) 53 | snippet(14) 54 | snippet(15) 55 | snippet(16) 56 | snippet(17) 57 | snippet(18) 58 | snippet(19) 59 | snippet(20) 60 | snippet(21) 61 | snippet(22) 62 | snippet(23) 63 | snippet(24) 64 | snippet(25) 65 | snippet(26) 66 | snippet(27) 67 | -------------------------------------------------------------------------------- /Chapter04/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter04) 28 | 29 | include(ExternalProject) 30 | find_package(Git REQUIRED) 31 | 32 | set(CMAKE_CXX_STANDARD 17) 33 | 34 | # ------------------------------------------------------------------------------ 35 | # Guideline Support Library 36 | # ------------------------------------------------------------------------------ 37 | 38 | list(APPEND GSL_CMAKE_ARGS 39 | -DGSL_TEST=OFF 40 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} 41 | ) 42 | 43 | ExternalProject_Add( 44 | gsl 45 | GIT_REPOSITORY https://github.com/Microsoft/GSL.git 46 | GIT_SHALLOW 1 47 | CMAKE_ARGS ${GSL_CMAKE_ARGS} 48 | PREFIX ${CMAKE_BINARY_DIR}/external/gsl/prefix 49 | TMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/tmp 50 | STAMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/stamp 51 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/gsl/download 52 | SOURCE_DIR ${CMAKE_BINARY_DIR}/external/gsl/src 53 | BINARY_DIR ${CMAKE_BINARY_DIR}/external/gsl/build 54 | ) 55 | 56 | # ------------------------------------------------------------------------------ 57 | # Snippets 58 | # ------------------------------------------------------------------------------ 59 | 60 | include_directories(${CMAKE_BINARY_DIR}/include) 61 | 62 | function(snippet number) 63 | add_executable(snippet${number} scratchpad.cpp) 64 | target_compile_definitions(snippet${number} PRIVATE SNIPPET${number}) 65 | add_dependencies(snippet${number} gsl) 66 | endfunction(snippet) 67 | 68 | snippet(01) 69 | snippet(02) 70 | snippet(03) 71 | snippet(04) 72 | snippet(05) 73 | snippet(06) 74 | snippet(07) 75 | snippet(08) 76 | snippet(09) 77 | snippet(10) 78 | snippet(11) 79 | snippet(12) 80 | snippet(13) 81 | snippet(14) 82 | snippet(15) 83 | snippet(16) 84 | snippet(17) 85 | snippet(18) 86 | snippet(19) 87 | snippet(20) 88 | snippet(21) 89 | snippet(22) 90 | snippet(23) 91 | snippet(24) 92 | snippet(25) 93 | snippet(26) 94 | snippet(27) 95 | snippet(28) 96 | snippet(29) 97 | snippet(30) 98 | snippet(31) 99 | snippet(32) 100 | snippet(33) 101 | snippet(34) 102 | snippet(35) 103 | snippet(36) 104 | -------------------------------------------------------------------------------- /Chapter04/scratchpad.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | // ----------------------------------------------------------------------------- 23 | // Section: Stream Based IO 24 | // ----------------------------------------------------------------------------- 25 | 26 | #if SNIPPET01 27 | 28 | #include 29 | 30 | int main(void) 31 | { 32 | if (auto i = 42; i > 0) { 33 | std::cout << "Hello World\n"; 34 | } 35 | } 36 | 37 | // > g++ scratchpad.cpp; ./a.out 38 | // Hello World 39 | 40 | #endif 41 | 42 | #if SNIPPET02 43 | 44 | #include 45 | 46 | int main(void) 47 | { 48 | switch(auto i = 42) { 49 | case 42: 50 | std::cout << "Hello World\n"; 51 | break; 52 | 53 | default: 54 | break; 55 | } 56 | } 57 | 58 | // > g++ scratchpad.cpp; ./a.out 59 | // Hello World 60 | 61 | #endif 62 | 63 | #if SNIPPET03 64 | 65 | #include 66 | 67 | constexpr const auto val = true; 68 | 69 | int main(void) 70 | { 71 | if (val) { 72 | std::cout << "Hello World\n"; 73 | } 74 | } 75 | 76 | // > g++ scratchpad.cpp; ./a.out 77 | // Hello World 78 | 79 | #endif 80 | 81 | #if SNIPPET04 82 | 83 | #include 84 | 85 | int main(void) 86 | { 87 | if constexpr (constexpr const auto i = 42; i > 0) { 88 | std::cout << "Hello World\n"; 89 | } 90 | } 91 | 92 | // > g++ scratchpad.cpp; ./a.out 93 | // Hello World 94 | 95 | #endif 96 | 97 | #if SNIPPET05 98 | 99 | #include 100 | 101 | int main(void) 102 | { 103 | static_assert(42 == 42, "the answer"); 104 | } 105 | 106 | // > g++ scratchpad.cpp; ./a.out 107 | // 108 | 109 | #endif 110 | 111 | #if SNIPPET06 112 | 113 | #include 114 | 115 | int main(void) 116 | { 117 | static_assert(42 == 42); 118 | } 119 | 120 | // > g++ scratchpad.cpp; ./a.out 121 | // 122 | 123 | #endif 124 | 125 | #if SNIPPET07 126 | 127 | #include 128 | 129 | namespace X::Y::Z 130 | { 131 | auto msg = "Hello World\n"; 132 | } 133 | 134 | int main(void) 135 | { 136 | std::cout << X::Y::Z::msg; 137 | } 138 | 139 | // > g++ scratchpad.cpp; ./a.out 140 | // Hello World 141 | 142 | #endif 143 | 144 | #if SNIPPET08 145 | 146 | #include 147 | 148 | namespace X 149 | { 150 | namespace Y 151 | { 152 | namespace Z 153 | { 154 | auto msg = "Hello World\n"; 155 | } 156 | } 157 | } 158 | 159 | int main(void) 160 | { 161 | std::cout << X::Y::Z::msg; 162 | } 163 | 164 | // > g++ scratchpad.cpp; ./a.out 165 | // Hello World 166 | 167 | #endif 168 | 169 | #if SNIPPET09 170 | 171 | #include 172 | 173 | std::pair 174 | give_me_a_pair() 175 | { 176 | return {"The answer is: ", 42}; 177 | } 178 | 179 | int main(void) 180 | { 181 | auto [msg, answer] = give_me_a_pair(); 182 | std::cout << msg << answer << '\n'; 183 | } 184 | 185 | // > g++ scratchpad.cpp; ./a.out 186 | // The answer is: 42 187 | 188 | #endif 189 | 190 | #if SNIPPET10 191 | 192 | #include 193 | #include 194 | 195 | std::pair 196 | give_me_a_pair() 197 | { 198 | return {"The answer is: ", 42}; 199 | } 200 | 201 | int main(void) 202 | { 203 | auto p = give_me_a_pair(); 204 | std::cout << std::get<0>(p) << std::get<1>(p) << '\n'; 205 | } 206 | 207 | // > g++ scratchpad.cpp; ./a.out 208 | // The answer is: 42 209 | 210 | #endif 211 | 212 | #if SNIPPET11 213 | 214 | #include 215 | 216 | struct mystruct 217 | { 218 | const char *msg; 219 | int answer; 220 | }; 221 | 222 | mystruct 223 | give_me_a_struct() 224 | { 225 | return {"The answer is: ", 42}; 226 | } 227 | 228 | int main(void) 229 | { 230 | auto [msg, answer] = give_me_a_struct(); 231 | std::cout << msg << answer << '\n'; 232 | } 233 | 234 | // > g++ scratchpad.cpp; ./a.out 235 | // The answer is: 42 236 | 237 | #endif 238 | 239 | #if SNIPPET12 240 | 241 | #include 242 | 243 | inline auto msg = "Hello World\n"; 244 | 245 | int main(void) 246 | { 247 | std::cout << msg; 248 | } 249 | 250 | // > g++ scratchpad.cpp; ./a.out 251 | // Hello World 252 | 253 | #endif 254 | 255 | #if SNIPPET13 256 | 257 | #include 258 | #include 259 | 260 | int main(void) 261 | { 262 | std::string_view str("Hello World\n"); 263 | std::cout << str; 264 | } 265 | 266 | // > g++ scratchpad.cpp; ./a.out 267 | // Hello World 268 | 269 | #endif 270 | 271 | #if SNIPPET14 272 | 273 | #include 274 | #include 275 | 276 | int main(void) 277 | { 278 | std::string_view str("Hello World"); 279 | 280 | std::cout << str.front() << '\n'; 281 | std::cout << str.back() << '\n'; 282 | std::cout << str.at(1) << '\n'; 283 | std::cout << str.data() << '\n'; 284 | } 285 | 286 | // > g++ scratchpad.cpp; ./a.out 287 | // H 288 | // d 289 | // e 290 | // Hello World 291 | 292 | #endif 293 | 294 | #if SNIPPET15 295 | 296 | #include 297 | #include 298 | 299 | int main(void) 300 | { 301 | std::string_view str("Hello World"); 302 | 303 | std::cout << str.size() << '\n'; 304 | std::cout << str.max_size() << '\n'; 305 | std::cout << str.empty() << '\n'; 306 | } 307 | 308 | // > g++ scratchpad.cpp; ./a.out 309 | // 11 310 | // 4611686018427387899 311 | // 0 312 | 313 | #endif 314 | 315 | #if SNIPPET16 316 | 317 | #include 318 | #include 319 | 320 | int main(void) 321 | { 322 | std::string_view str("Hello World"); 323 | 324 | str.remove_prefix(1); 325 | str.remove_suffix(1); 326 | std::cout << str << '\n'; 327 | } 328 | 329 | // > g++ scratchpad.cpp; ./a.out 330 | // ello Worl 331 | 332 | #endif 333 | 334 | #if SNIPPET17 335 | 336 | #include 337 | #include 338 | 339 | int main(void) 340 | { 341 | std::string_view str("Hello World"); 342 | std::cout << str.substr(0, 5) << '\n'; 343 | } 344 | 345 | // > g++ scratchpad.cpp; ./a.out 346 | // Hello 347 | 348 | #endif 349 | 350 | #if SNIPPET18 351 | 352 | #include 353 | #include 354 | 355 | int main(void) 356 | { 357 | std::string_view str("Hello World"); 358 | 359 | if (str.compare("Hello World") == 0) { 360 | std::cout << "Hello World\n"; 361 | } 362 | 363 | std::cout << str.compare("Hello") << '\n'; 364 | std::cout << str.compare("World") << '\n'; 365 | } 366 | 367 | // > g++ scratchpad.cpp; ./a.out 368 | // Hello World 369 | // 6 370 | // -1 371 | 372 | #endif 373 | 374 | #if SNIPPET19 375 | 376 | #include 377 | 378 | int main(void) 379 | { 380 | std::string_view str("Hello this is a test of Hello World"); 381 | 382 | std::cout << str.find("Hello") << '\n'; 383 | std::cout << str.rfind("Hello") << '\n'; 384 | std::cout << str.find_first_of("Hello") << '\n'; 385 | std::cout << str.find_last_of("Hello") << '\n'; 386 | std::cout << str.find_first_not_of("Hello") << '\n'; 387 | std::cout << str.find_last_not_of("Hello") << '\n'; 388 | } 389 | 390 | // > g++ scratchpad.cpp; ./a.out 391 | // 0 392 | // 24 393 | // 0 394 | // 33 395 | // 5 396 | // 34 397 | 398 | #endif 399 | 400 | #if SNIPPET20 401 | 402 | #include 403 | #include 404 | 405 | struct mystruct { 406 | int data; 407 | }; 408 | 409 | int main(void) 410 | { 411 | auto myany = std::make_any(42); 412 | std::cout << std::any_cast(myany) << '\n'; 413 | 414 | myany = 4.2; 415 | std::cout << std::any_cast(myany) << '\n'; 416 | 417 | myany = mystruct{42}; 418 | std::cout << std::any_cast(myany).data << '\n'; 419 | } 420 | 421 | // > g++ scratchpad.cpp; ./a.out 422 | // 42 423 | // 4.2 424 | // 42 425 | 426 | #endif 427 | 428 | #if SNIPPET21 429 | 430 | #include 431 | #include 432 | 433 | int main(void) 434 | { 435 | std::variant v = 42; 436 | std::cout << std::get(v) << '\n'; 437 | 438 | v = 4.2; 439 | std::cout << std::get(v) << '\n'; 440 | } 441 | 442 | // > g++ scratchpad.cpp; ./a.out 443 | // 42 444 | // 4.2 445 | 446 | #endif 447 | 448 | #if SNIPPET22 449 | 450 | #include 451 | #include 452 | 453 | class myclass 454 | { 455 | public: 456 | int val; 457 | 458 | myclass(int v) : 459 | val{v} 460 | { 461 | std::cout << "constructed\n"; 462 | } 463 | }; 464 | 465 | int main(void) 466 | { 467 | std::optional o; 468 | std::cout << "created, but not constructed\n"; 469 | 470 | if (o) { 471 | std::cout << "Attempt #1: " << o->val << '\n'; 472 | } 473 | 474 | o = myclass{42}; 475 | 476 | if (o) { 477 | std::cout << "Attempt #2: " << o->val << '\n'; 478 | } 479 | } 480 | 481 | // > g++ scratchpad.cpp; ./a.out 482 | // created, but not constructed 483 | // constructed 484 | // Attempt #2: 42 485 | 486 | #endif 487 | 488 | #if SNIPPET23 489 | 490 | #include 491 | 492 | class myclass 493 | { 494 | public: 495 | myclass() 496 | { 497 | std::cout << "Hello from constructor\n"; 498 | } 499 | 500 | ~myclass() 501 | { 502 | std::cout << "Hello from destructor\n"; 503 | } 504 | }; 505 | 506 | int main(void) 507 | { 508 | myclass c; 509 | } 510 | 511 | // > g++ scratchpad.cpp; ./a.out 512 | // Hello from constructor 513 | // Hello from destructor 514 | 515 | #endif 516 | 517 | #if SNIPPET24 518 | 519 | #include 520 | 521 | class myclass 522 | { 523 | int *ptr; 524 | 525 | public: 526 | myclass() : 527 | ptr{new int(42)} 528 | { } 529 | 530 | ~myclass() 531 | { 532 | delete ptr; 533 | } 534 | 535 | int get() 536 | { 537 | return *ptr; 538 | } 539 | }; 540 | 541 | int main(void) 542 | { 543 | myclass c; 544 | std::cout << "The answer is: " << c.get() << '\n'; 545 | } 546 | 547 | // > g++ scratchpad.cpp; ./a.out 548 | // The answer is: 42 549 | 550 | #endif 551 | 552 | #if SNIPPET25 553 | 554 | #include 555 | 556 | class myclass 557 | { 558 | FILE *m_file; 559 | 560 | public: 561 | myclass(const char *filename) : 562 | m_file{fopen(filename, "rb")} 563 | { 564 | if (m_file == 0) { 565 | throw std::runtime_error("unable to open file"); 566 | } 567 | } 568 | 569 | ~myclass() 570 | { 571 | fclose(m_file); 572 | std::clog << "Hello from destructor\n"; 573 | } 574 | }; 575 | 576 | int main(void) 577 | { 578 | myclass c1("test.txt"); 579 | 580 | try { 581 | myclass c2("does_not_exist.txt"); 582 | } 583 | catch(const std::exception &e) { 584 | std::cout << "exception: " << e.what() << '\n'; 585 | } 586 | } 587 | 588 | // > g++ scratchpad.cpp; touch test.txt; ./a.out 589 | // exception: unable to open file 590 | // Hello from destructor 591 | 592 | #endif 593 | 594 | #if SNIPPET26 595 | 596 | #include 597 | 598 | void init(int *p) 599 | { 600 | *p = 0; 601 | } 602 | 603 | int main(void) 604 | { 605 | auto p = new int; 606 | init(p); 607 | delete p; 608 | } 609 | 610 | // > g++ scratchpad.cpp; ./a.out 611 | // 612 | 613 | #endif 614 | 615 | #if SNIPPET27 616 | 617 | #include 618 | 619 | void init(int *p) 620 | { 621 | *p = 0; 622 | } 623 | 624 | int main(void) 625 | { 626 | gsl::owner p = new int; 627 | init(p); 628 | delete p; 629 | } 630 | 631 | // > g++ scratchpad.cpp; ./a.out 632 | // 633 | 634 | #endif 635 | 636 | #if SNIPPET28 637 | 638 | #include 639 | 640 | gsl::not_null 641 | test(gsl::not_null p) 642 | { 643 | return p; 644 | } 645 | 646 | int main(void) 647 | { 648 | auto p1 = std::make_unique(); 649 | auto p2 = test(gsl::not_null(p1.get())); 650 | } 651 | 652 | // > g++ scratchpad.cpp; ./a.out 653 | // 654 | 655 | #endif 656 | 657 | #if SNIPPET29 658 | 659 | #define GSL_THROW_ON_CONTRACT_VIOLATION 660 | #include 661 | #include 662 | 663 | int main(void) 664 | { 665 | int array[5] = {1, 2, 3, 4, 5}; 666 | auto span = gsl::span(array); 667 | 668 | for (const auto &elem : span) { 669 | std::clog << elem << '\n'; 670 | } 671 | 672 | for (auto i = 0; i < 5; i++) { 673 | std::clog << span[i] << '\n'; 674 | } 675 | 676 | try { 677 | std::clog << span[5] << '\n'; 678 | } 679 | catch(const gsl::fail_fast &e) { 680 | std::cout << "exception: " << e.what() << '\n'; 681 | } 682 | } 683 | 684 | // > g++ scratchpad.cpp; ./a.out 685 | // 1 686 | // 2 687 | // 3 688 | // 4 689 | // 5 690 | // 1 691 | // 2 692 | // 3 693 | // 4 694 | // 5 695 | // exception: GSL: Precondition failure at ... 696 | 697 | #endif 698 | 699 | #if SNIPPET30 700 | 701 | #include 702 | #include 703 | 704 | int main(void) 705 | { 706 | gsl::cstring_span<> str = gsl::ensure_z("Hello World\n"); 707 | std::cout << str.data(); 708 | 709 | for (const auto &elem : str) { 710 | std::clog << elem; 711 | } 712 | } 713 | 714 | // > g++ scratchpad.cpp; ./a.out 715 | // Hello World 716 | // Hello World 717 | 718 | #endif 719 | 720 | #if SNIPPET31 721 | 722 | #define GSL_THROW_ON_CONTRACT_VIOLATION 723 | #include 724 | #include 725 | 726 | int main(void) 727 | { 728 | try { 729 | Expects(false); 730 | } 731 | catch(const gsl::fail_fast &e) { 732 | std::cout << "exception: " << e.what() << '\n'; 733 | } 734 | } 735 | 736 | // > g++ scratchpad.cpp; ./a.out 737 | // exception: GSL: Precondition failure at ... 738 | 739 | #endif 740 | 741 | #if SNIPPET32 742 | 743 | #define GSL_THROW_ON_CONTRACT_VIOLATION 744 | #include 745 | #include 746 | 747 | int 748 | test(int i) 749 | { 750 | Expects(i >= 0 && i < 41); 751 | i++; 752 | 753 | Ensures(i < 42); 754 | return i; 755 | } 756 | 757 | int main(void) 758 | { 759 | test(0); 760 | 761 | try { 762 | test(42); 763 | } 764 | catch(const gsl::fail_fast &e) { 765 | std::cout << "exception: " << e.what() << '\n'; 766 | } 767 | } 768 | 769 | // > g++ scratchpad.cpp; ./a.out 770 | // exception: GSL: Precondition failure at ... 771 | 772 | #endif 773 | 774 | #if SNIPPET33 775 | 776 | #include 777 | #include 778 | 779 | int 780 | test(int i) 781 | { 782 | Expects(i < 42); 783 | i = 42; 784 | Ensures(i == 42); 785 | 786 | return i; 787 | } 788 | 789 | int main(void) 790 | { 791 | std::cout << test(0) << '\n'; 792 | } 793 | 794 | // > g++ scratchpad.cpp; ./a.out 795 | // 42 796 | 797 | #endif 798 | 799 | #if SNIPPET34 800 | 801 | #define concat1(a,b) a ## b 802 | #define concat2(a,b) concat1(a,b) 803 | #define ___ concat2(dont_care, __COUNTER__) 804 | 805 | #include 806 | #include 807 | 808 | int main(void) 809 | { 810 | auto ___ = gsl::finally([]{ 811 | std::cout << "Hello World\n"; 812 | }); 813 | } 814 | 815 | // > g++ scratchpad.cpp; ./a.out 816 | // Hello World 817 | 818 | #endif 819 | 820 | #if SNIPPET35 821 | 822 | #include 823 | #include 824 | 825 | int main(void) 826 | { 827 | uint64_t val = 42; 828 | 829 | auto val1 = gsl::narrow(val); 830 | auto val2 = gsl::narrow_cast(val); 831 | } 832 | 833 | // > g++ scratchpad.cpp; ./a.out 834 | // 835 | 836 | #endif 837 | 838 | #if SNIPPET36 839 | 840 | #define GSL_THROW_ON_CONTRACT_VIOLATION 841 | #include 842 | #include 843 | 844 | int main(void) 845 | { 846 | uint64_t val = 0xFFFFFFFFFFFFFFFF; 847 | 848 | try { 849 | gsl::narrow(val); 850 | } 851 | catch(...) { 852 | std::cout << "narrow failed\n"; 853 | } 854 | } 855 | 856 | // > g++ scratchpad.cpp; ./a.out 857 | // narrow failed 858 | 859 | #endif 860 | -------------------------------------------------------------------------------- /Chapter05/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter05) 28 | 29 | include(ExternalProject) 30 | find_package(Git REQUIRED) 31 | 32 | set(CMAKE_CXX_STANDARD 17) 33 | 34 | # ------------------------------------------------------------------------------ 35 | # Snippets 36 | # ------------------------------------------------------------------------------ 37 | 38 | include_directories(${CMAKE_BINARY_DIR}/include) 39 | 40 | function(snippet number) 41 | add_executable(snippet${number} scratchpad.cpp) 42 | target_compile_definitions(snippet${number} PRIVATE SNIPPET${number}) 43 | endfunction(snippet) 44 | 45 | snippet(01) 46 | snippet(02) 47 | snippet(03) 48 | snippet(04) 49 | snippet(05) 50 | snippet(06) 51 | snippet(07) 52 | snippet(08) 53 | snippet(09) 54 | snippet(10) 55 | snippet(11) 56 | snippet(12) 57 | snippet(13) 58 | snippet(14) 59 | snippet(15) 60 | snippet(16) 61 | snippet(17) 62 | snippet(18) 63 | snippet(19) 64 | snippet(20) 65 | snippet(21) 66 | snippet(22) 67 | snippet(23) 68 | snippet(24) 69 | snippet(25) 70 | snippet(26) 71 | snippet(27) 72 | snippet(28) 73 | snippet(29) 74 | snippet(30) 75 | snippet(31) 76 | snippet(32) 77 | snippet(33) 78 | snippet(34) 79 | -------------------------------------------------------------------------------- /Chapter05/scratchpad.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #if SNIPPET01 23 | 24 | int test() 25 | { 26 | int i = 1; 27 | int j = 2; 28 | 29 | return i + j; 30 | } 31 | 32 | int main(void) 33 | { 34 | test(); 35 | } 36 | 37 | // > g++ scratchpad.cpp; ./a.out 38 | // 39 | 40 | #endif 41 | 42 | #if SNIPPET02 43 | 44 | int test(int val1, int val2) 45 | { 46 | return val1 + val2; 47 | } 48 | 49 | int main(void) 50 | { 51 | auto ret = test(42, 42); 52 | } 53 | 54 | // > g++ scratchpad.cpp; ./a.out 55 | // 56 | 57 | #endif 58 | 59 | #if SNIPPET03 60 | 61 | #include 62 | 63 | struct mystruct 64 | { 65 | uint64_t data1; 66 | uint64_t data2; 67 | }; 68 | 69 | mystruct test() 70 | { 71 | return {1, 2}; 72 | } 73 | 74 | int main(void) 75 | { 76 | auto ret = test(); 77 | } 78 | 79 | // > g++ scratchpad.cpp; ./a.out 80 | // 81 | 82 | #endif 83 | 84 | #if SNIPPET04 85 | 86 | #include 87 | 88 | struct mystruct 89 | { 90 | uint64_t data1; 91 | uint64_t data2; 92 | uint64_t data3; 93 | }; 94 | 95 | mystruct test() 96 | { 97 | return {1, 2, 3}; 98 | } 99 | 100 | int main(void) 101 | { 102 | auto ret = test(); 103 | } 104 | 105 | // > g++ scratchpad.cpp; ./a.out 106 | // 107 | 108 | #endif 109 | 110 | #if SNIPPET05 111 | 112 | #include 113 | #include 114 | 115 | void test(int i) 116 | { 117 | if (i == 42) { 118 | throw 42; 119 | } 120 | } 121 | 122 | int main(void) 123 | { 124 | try { 125 | test(1); 126 | std::cout << "attempt #1: passed\n"; 127 | 128 | test(42); 129 | std::cout << "attempt #2: passed\n"; 130 | } 131 | catch(...) { 132 | std::cout << "exception catch\n"; 133 | } 134 | } 135 | 136 | // > g++ scratchpad.cpp; ./a.out 137 | // attempt #1: passed 138 | // exception catch 139 | 140 | #endif 141 | 142 | #if SNIPPET06 143 | 144 | int main(void) 145 | { 146 | } 147 | 148 | // > g++ scratchpad.cpp; ./a.out 149 | // 150 | 151 | #endif 152 | 153 | #if SNIPPET07 154 | 155 | #include 156 | 157 | int main(void) 158 | { 159 | std::cout << "The answer is: 42\n"; 160 | } 161 | 162 | // > g++ scratchpad.cpp; ./a.out 163 | // The answer is: 42 164 | 165 | #endif 166 | 167 | #if SNIPPET08 168 | 169 | #include 170 | #include 171 | 172 | int main(void) 173 | { 174 | fork(); 175 | std::cout << "Hello World\n"; 176 | } 177 | 178 | // > g++ scratchpad.cpp; ./a.out 179 | // Hello World 180 | // Hello World 181 | 182 | #endif 183 | 184 | #if SNIPPET09 185 | 186 | #include 187 | #include 188 | 189 | int data = 0; 190 | 191 | int main(void) 192 | { 193 | if (fork() != 0) 194 | { 195 | data = 42; 196 | } 197 | 198 | std::cout << "The answer is: " << data << '\n'; 199 | } 200 | 201 | // > g++ scratchpad.cpp; ./a.out 202 | // The answer is: 42 203 | // The answer is: 0 204 | 205 | #endif 206 | 207 | #if SNIPPET10 208 | 209 | #include 210 | #include 211 | 212 | int main(void) 213 | { 214 | if (fork() != 0) { 215 | std::cout << "Hello\n"; 216 | } 217 | else { 218 | std::cout << "World\n"; 219 | } 220 | } 221 | 222 | // > g++ scratchpad.cpp; ./a.out 223 | // Hello 224 | // World 225 | 226 | #endif 227 | 228 | #if SNIPPET11 229 | 230 | #include 231 | #include 232 | 233 | int main(void) 234 | { 235 | fork(); 236 | fork(); 237 | std::cout << "Hello World\n"; 238 | } 239 | 240 | // > g++ scratchpad.cpp; ./a.out 241 | // Hello World 242 | // Hello World 243 | // Hello World 244 | // Hello World 245 | 246 | #endif 247 | 248 | #if SNIPPET12 249 | 250 | #include 251 | #include 252 | 253 | int main(void) 254 | { 255 | auto id1 = fork(); 256 | std::cout << "id1: " << id1 << '\n'; 257 | 258 | auto id2 = fork(); 259 | std::cout << "id2: " << id2 << '\n'; 260 | std::cout << "-----------\n"; 261 | } 262 | 263 | // > g++ scratchpad.cpp; ./a.out 264 | // id1: 14181 265 | // id2: 14182 266 | // ----------- 267 | // id1: 0 268 | // id2: 14183 269 | // ----------- 270 | // id2: 0 271 | // ----------- 272 | // id2: 0 273 | // ----------- 274 | 275 | #endif 276 | 277 | #if SNIPPET13 278 | 279 | #include 280 | #include 281 | 282 | int main(void) 283 | { 284 | fork(); 285 | fork(); 286 | fork(); 287 | std::cout << "Hello World\n"; 288 | } 289 | 290 | // > g++ scratchpad.cpp; ./a.out 291 | // Hello World 292 | // Hello World 293 | // Hello World 294 | // Hello World 295 | // Hello World 296 | // Hello World 297 | // Hello World 298 | // Hello World 299 | 300 | #endif 301 | 302 | #if SNIPPET14 303 | 304 | #include 305 | #include 306 | 307 | int main(void) 308 | { 309 | if (fork() != 0) { 310 | std::cout << "The\n"; 311 | } 312 | else { 313 | if (fork() != 0) { 314 | std::cout << "answer\n"; 315 | } 316 | else { 317 | if (fork() != 0) { 318 | std::cout << "is\n"; 319 | } 320 | else { 321 | std::cout << 42 << '\n'; 322 | } 323 | } 324 | } 325 | } 326 | 327 | // > g++ scratchpad.cpp; ./a.out 328 | // The 329 | // answer 330 | // is 331 | // 42 332 | 333 | #endif 334 | 335 | #if SNIPPET15 336 | 337 | #include 338 | #include 339 | #include 340 | 341 | int main(void) 342 | { 343 | if (fork() != 0) { 344 | std::cout << "parent\n"; 345 | wait(nullptr); 346 | } 347 | else { 348 | std::cout << "child\n"; 349 | } 350 | } 351 | 352 | // > g++ scratchpad.cpp; ./a.out 353 | // parent 354 | // child 355 | 356 | #endif 357 | 358 | #if SNIPPET16 359 | 360 | #include 361 | #include 362 | #include 363 | 364 | int main(void) 365 | { 366 | int id; 367 | 368 | auto id1 = fork(); 369 | auto id2 = fork(); 370 | auto id3 = fork(); 371 | 372 | while(1) 373 | { 374 | id = wait(nullptr); 375 | 376 | if (id == -1) 377 | break; 378 | 379 | if (id == id1) 380 | std::cout << "child #1 finished\n"; 381 | 382 | if (id == id2) 383 | std::cout << "child #2 finished\n"; 384 | 385 | if (id == id3) 386 | std::cout << "child #3 finished\n"; 387 | } 388 | 389 | if (id1 != 0 && id2 != 0 && id3 != 0) 390 | std::cout << "parent done\n"; 391 | } 392 | 393 | // > g++ scratchpad.cpp; ./a.out 394 | // child #1 finished 395 | // child #2 finished 396 | // child #3 finished 397 | // parent done 398 | 399 | #endif 400 | 401 | #if SNIPPET17 402 | 403 | #include 404 | #include 405 | #include 406 | 407 | int main(void) 408 | { 409 | if (fork() != 0) { 410 | std::cout << "parent\n"; 411 | wait(nullptr); 412 | } 413 | else { 414 | std::cout << "child\n"; 415 | } 416 | } 417 | 418 | // > g++ scratchpad.cpp; ./a.out 419 | // parent 420 | // child 421 | 422 | #endif 423 | 424 | #if SNIPPET18 425 | 426 | #include 427 | #include 428 | #include 429 | 430 | int main(void) 431 | { 432 | if (fork() != 0) { 433 | sleep(1); 434 | std::cout << "parent\n"; 435 | wait(nullptr); 436 | } 437 | else { 438 | std::cout << "child\n"; 439 | } 440 | } 441 | 442 | // > g++ scratchpad.cpp; ./a.out 443 | // child 444 | // parent 445 | 446 | #endif 447 | 448 | #if SNIPPET19 449 | 450 | #include 451 | #include 452 | #include 453 | 454 | #include 455 | #include 456 | #include 457 | 458 | class mypipe 459 | { 460 | std::array m_handles; 461 | 462 | public: 463 | mypipe() 464 | { 465 | if (pipe(m_handles.data()) < 0) { 466 | exit(1); 467 | } 468 | } 469 | 470 | ~mypipe() 471 | { 472 | close(m_handles.at(0)); 473 | close(m_handles.at(1)); 474 | } 475 | 476 | std::string 477 | read() 478 | { 479 | std::array buf; 480 | std::size_t bytes = ::read(m_handles.at(0), buf.data(), buf.size()); 481 | 482 | if (bytes > 0) { 483 | return {buf.data(), bytes}; 484 | } 485 | 486 | return {}; 487 | } 488 | 489 | void 490 | write(const std::string &msg) 491 | { 492 | ::write(m_handles.at(1), msg.data(), msg.size()); 493 | } 494 | }; 495 | 496 | int main(void) 497 | { 498 | mypipe p; 499 | 500 | if (fork() != 0) { 501 | sleep(1); 502 | std::cout << "parent\n"; 503 | 504 | p.write("done"); 505 | wait(nullptr); 506 | } 507 | else { 508 | auto msg = p.read(); 509 | 510 | std::cout << "child\n"; 511 | std::cout << "msg: " << msg << '\n'; 512 | } 513 | } 514 | 515 | // > g++ scratchpad.cpp -std=c++17; ./a.out 516 | // parent 517 | // child 518 | // msg: done 519 | 520 | #endif 521 | 522 | #if SNIPPET20 523 | 524 | #include 525 | #include 526 | #include 527 | #include 528 | #include 529 | 530 | char * 531 | get_shared_memory() 532 | { 533 | auto key = ftok("myfile", 42); 534 | auto shm = shmget(key, 0x1000, 0666 | IPC_CREAT); 535 | 536 | return static_cast(shmat(shm, nullptr, 0)); 537 | } 538 | 539 | int main(void) 540 | { 541 | if (fork() != 0) { 542 | sleep(1); 543 | std::cout << "parent\n"; 544 | 545 | auto msg = get_shared_memory(); 546 | msg[0] = 42; 547 | 548 | wait(nullptr); 549 | } 550 | else { 551 | auto msg = get_shared_memory(); 552 | while(msg[0] != 42); 553 | 554 | std::cout << "child\n"; 555 | } 556 | } 557 | 558 | // > g++ scratchpad.cpp; ./a.out 559 | // parent 560 | // child 561 | 562 | #endif 563 | 564 | #if SNIPPET21 565 | 566 | #include 567 | #include 568 | 569 | int main(void) 570 | { 571 | execl("/bin/ls", "ls", nullptr); 572 | std::cout << "Hello World\n"; 573 | } 574 | 575 | // > g++ scratchpad.cpp; ./a.out 576 | // 577 | 578 | #endif 579 | 580 | 581 | #if SNIPPET22 582 | 583 | #include 584 | #include 585 | 586 | int main(void) 587 | { 588 | system("ls"); 589 | std::cout << "Hello World\n"; 590 | } 591 | 592 | // > g++ scratchpad.cpp; ./a.out 593 | // 594 | // Hello World 595 | 596 | #endif 597 | 598 | #if SNIPPET23 599 | 600 | #include 601 | #include 602 | #include 603 | 604 | void 605 | mysystem(const char *command) 606 | { 607 | if (fork() == 0) { 608 | execlp(command, command, nullptr); 609 | } 610 | else { 611 | wait(nullptr); 612 | } 613 | } 614 | 615 | int main(void) 616 | { 617 | mysystem("ls"); 618 | std::cout << "Hello World\n"; 619 | } 620 | 621 | // > g++ scratchpad.cpp; ./a.out 622 | // 623 | // Hello World 624 | 625 | #endif 626 | 627 | #if SNIPPET24 628 | 629 | #include 630 | #include 631 | 632 | int main(void) 633 | { 634 | execl("/bin/ls", "ls", "-al", nullptr); 635 | } 636 | 637 | // > g++ scratchpad.cpp; ./a.out 638 | // 639 | 640 | #endif 641 | 642 | 643 | #if SNIPPET25 644 | 645 | #include 646 | #include 647 | 648 | int main(void) 649 | { 650 | const char *envp[] = {"ENV1=1", "ENV2=2", nullptr}; 651 | execle("/bin/ls", "ls", nullptr, envp); 652 | } 653 | 654 | // > g++ scratchpad.cpp; ./a.out 655 | // 656 | 657 | #endif 658 | 659 | #if SNIPPET26 660 | 661 | #include 662 | #include 663 | 664 | int main(void) 665 | { 666 | execlp("ls", "ls", nullptr); 667 | } 668 | 669 | // > g++ scratchpad.cpp; ./a.out 670 | // 671 | 672 | #endif 673 | 674 | #if SNIPPET27 675 | 676 | #include 677 | #include 678 | 679 | int main(void) 680 | { 681 | const char *argv[] = {"ls", nullptr}; 682 | execv("/bin/ls", const_cast(argv)); 683 | } 684 | 685 | // > g++ scratchpad.cpp; ./a.out 686 | // 687 | 688 | #endif 689 | 690 | #if SNIPPET28 691 | 692 | #include 693 | #include 694 | 695 | int main(void) 696 | { 697 | const char *argv[] = {"ls", nullptr}; 698 | const char *envp[] = {"ENV1=1", "ENV2=2", nullptr}; 699 | 700 | execve( 701 | "/bin/ls", 702 | const_cast(argv), 703 | const_cast(envp) 704 | ); 705 | } 706 | 707 | // > g++ scratchpad.cpp; ./a.out 708 | // 709 | 710 | #endif 711 | 712 | #if SNIPPET29 713 | 714 | #include 715 | #include 716 | 717 | int main(void) 718 | { 719 | const char *argv[] = {"ls", nullptr}; 720 | execvp("ls", const_cast(argv)); 721 | } 722 | 723 | // > g++ scratchpad.cpp; ./a.out 724 | // 725 | 726 | #endif 727 | 728 | #if SNIPPET30 729 | 730 | #include 731 | #include 732 | #include 733 | 734 | #include 735 | #include 736 | #include 737 | 738 | class mypipe 739 | { 740 | std::array m_handles; 741 | 742 | public: 743 | mypipe() 744 | { 745 | if (pipe(m_handles.data()) < 0) { 746 | exit(1); 747 | } 748 | } 749 | 750 | ~mypipe() 751 | { 752 | close(m_handles.at(0)); 753 | close(m_handles.at(1)); 754 | } 755 | 756 | std::string 757 | read() 758 | { 759 | std::array buf; 760 | std::size_t bytes = ::read(m_handles.at(0), buf.data(), buf.size()); 761 | 762 | if (bytes > 0) { 763 | return {buf.data(), bytes}; 764 | } 765 | 766 | return {}; 767 | } 768 | 769 | void 770 | redirect() 771 | { 772 | dup2(m_handles.at(1), STDOUT_FILENO); 773 | close(m_handles.at(0)); 774 | close(m_handles.at(1)); 775 | } 776 | }; 777 | 778 | int main(void) 779 | { 780 | mypipe p; 781 | 782 | if(fork() == 0) { 783 | p.redirect(); 784 | execlp("ls", "ls", nullptr); 785 | } 786 | else { 787 | wait(nullptr); 788 | std::cout << p.read() << '\n'; 789 | } 790 | } 791 | 792 | // > g++ scratchpad.cpp; ./a.out 793 | // 794 | 795 | #endif 796 | 797 | #if SNIPPET31 798 | 799 | #include 800 | #include 801 | 802 | int main(void) 803 | { 804 | while(true) { 805 | std::cout << "Hello World\n"; 806 | sleep(1); 807 | } 808 | } 809 | 810 | // > g++ scratchpad.cpp; ./a.out 811 | // Hello World 812 | // Hello World 813 | // Hello World 814 | // ... 815 | // ^C 816 | 817 | #endif 818 | 819 | #if SNIPPET32 820 | 821 | #include 822 | #include 823 | #include 824 | 825 | void handler(int sig) 826 | { 827 | if (sig == SIGINT) 828 | { 829 | std::cout << "handler called\n"; 830 | } 831 | } 832 | 833 | int main(void) 834 | { 835 | signal(SIGINT, handler); 836 | 837 | for (auto i = 0; i < 10; i++) 838 | { 839 | std::cout << "Hello World\n"; 840 | sleep(1); 841 | } 842 | } 843 | 844 | // > g++ scratchpad.cpp; ./a.out 845 | // Hello World 846 | // Hello World 847 | // ^Chandler called 848 | // Hello World 849 | // ^Chandler called 850 | // Hello World 851 | // ^Chandler called 852 | // Hello World 853 | // ^Chandler called 854 | // Hello World 855 | // Hello World 856 | // Hello World 857 | // Hello World 858 | // Hello World 859 | 860 | #endif 861 | 862 | #if SNIPPET33 863 | 864 | #include 865 | #include 866 | #include 867 | 868 | auto loop = true; 869 | 870 | void handler(int sig) 871 | { 872 | if (sig == SIGINT) 873 | { 874 | std::cout << "handler called\n"; 875 | loop = false; 876 | } 877 | } 878 | 879 | int main(void) 880 | { 881 | signal(SIGINT, handler); 882 | 883 | while(loop) { 884 | std::cout << "Hello World\n"; 885 | sleep(1); 886 | } 887 | } 888 | 889 | // > g++ scratchpad.cpp; ./a.out 890 | // Hello World 891 | // Hello World 892 | // ^Chandler called 893 | 894 | #endif 895 | 896 | #if SNIPPET34 897 | 898 | #include 899 | #include 900 | #include 901 | 902 | #include 903 | 904 | void 905 | mysystem(const char *command) 906 | { 907 | if(auto id = fork(); id > 0) { 908 | sleep(2); 909 | kill(id, SIGINT); 910 | } 911 | else { 912 | execlp(command, command, nullptr); 913 | } 914 | } 915 | 916 | int main(void) 917 | { 918 | mysystem("b.out"); 919 | } 920 | 921 | // > g++ scratchpad.cpp -std=c++17; ./a.out 922 | // 923 | 924 | #endif 925 | -------------------------------------------------------------------------------- /Chapter06/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter06) 28 | 29 | include(ExternalProject) 30 | find_package(Git REQUIRED) 31 | 32 | set(CMAKE_CXX_STANDARD 17) 33 | 34 | # ------------------------------------------------------------------------------ 35 | # Guideline Support Library 36 | # ------------------------------------------------------------------------------ 37 | 38 | list(APPEND GSL_CMAKE_ARGS 39 | -DGSL_TEST=OFF 40 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} 41 | ) 42 | 43 | ExternalProject_Add( 44 | gsl 45 | GIT_REPOSITORY https://github.com/Microsoft/GSL.git 46 | GIT_SHALLOW 1 47 | CMAKE_ARGS ${GSL_CMAKE_ARGS} 48 | PREFIX ${CMAKE_BINARY_DIR}/external/gsl/prefix 49 | TMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/tmp 50 | STAMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/stamp 51 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/gsl/download 52 | SOURCE_DIR ${CMAKE_BINARY_DIR}/external/gsl/src 53 | BINARY_DIR ${CMAKE_BINARY_DIR}/external/gsl/build 54 | ) 55 | 56 | # ------------------------------------------------------------------------------ 57 | # Executable 58 | # ------------------------------------------------------------------------------ 59 | 60 | include_directories(${CMAKE_BINARY_DIR}/include) 61 | 62 | add_executable(example1 example1.cpp) 63 | add_dependencies(example1 gsl) 64 | 65 | add_executable(example2 example2.cpp) 66 | add_dependencies(example2 gsl) 67 | 68 | # ------------------------------------------------------------------------------ 69 | # Snippets 70 | # ------------------------------------------------------------------------------ 71 | 72 | function(snippet number) 73 | add_executable(snippet${number} scratchpad.cpp) 74 | target_compile_definitions(snippet${number} PRIVATE SNIPPET${number}) 75 | endfunction(snippet) 76 | 77 | snippet(01) 78 | snippet(02) 79 | snippet(03) 80 | snippet(04) 81 | snippet(05) 82 | snippet(06) 83 | snippet(07) 84 | snippet(08) 85 | snippet(09) 86 | snippet(10) 87 | snippet(11) 88 | snippet(12) 89 | snippet(13) 90 | snippet(14) 91 | snippet(15) 92 | snippet(16) 93 | snippet(17) 94 | snippet(18) 95 | snippet(19) 96 | snippet(20) 97 | snippet(21) 98 | snippet(22) 99 | snippet(23) 100 | snippet(24) 101 | snippet(25) 102 | snippet(26) 103 | snippet(27) 104 | snippet(28) 105 | snippet(29) 106 | snippet(30) 107 | snippet(31) 108 | snippet(32) 109 | snippet(33) 110 | snippet(34) 111 | snippet(35) 112 | snippet(36) 113 | -------------------------------------------------------------------------------- /Chapter06/example1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | 24 | #include 25 | using namespace gsl; 26 | 27 | void 28 | handle_help() 29 | { 30 | std::cout 31 | << "Usage: echo [SHORT-OPTION]... [STRING]...\n" 32 | << " or: echo LONG-OPTION\n" 33 | << "Echo the STRING(s) to standard output.\n" 34 | << "\n" 35 | << " -n do not output the trailing newline\n" 36 | << " --help display this help and exit\n" 37 | << " --version output version information and exit\n"; 38 | 39 | ::exit(EXIT_SUCCESS); 40 | } 41 | 42 | void 43 | handle_version() 44 | { 45 | std::cout 46 | << "echo (example) 1.0\n" 47 | << "Copyright (C) ???\n" 48 | << "\n" 49 | << "Written by Rian Quinn.\n"; 50 | 51 | ::exit(EXIT_SUCCESS); 52 | } 53 | 54 | int 55 | protected_main(int argc, char **argv) 56 | { 57 | auto endl = true; 58 | auto args = make_span(argv, argc); 59 | 60 | for (int i = 1, num = 0; i < argc; i++) { 61 | cstring_span<> span_arg = ensure_z(args.at(i)); 62 | 63 | if (span_arg == "-n") { 64 | endl = false; 65 | continue; 66 | } 67 | 68 | if (span_arg == "--help") { 69 | handle_help(); 70 | } 71 | 72 | if (span_arg == "--version") { 73 | handle_version(); 74 | } 75 | 76 | if (num++ > 0) { 77 | std::cout << " "; 78 | } 79 | 80 | std::cout << span_arg.data(); 81 | } 82 | 83 | if (endl) { 84 | std::cout << '\n'; 85 | } 86 | 87 | return EXIT_SUCCESS; 88 | } 89 | 90 | int 91 | main(int argc, char **argv) 92 | { 93 | try { 94 | return protected_main(argc, argv); 95 | } 96 | catch (const std::exception &e) { 97 | std::cerr << "Caught unhandled exception:\n"; 98 | std::cerr << " - what(): " << e.what() << '\n'; 99 | } 100 | catch (...) { 101 | std::cerr << "Caught unknown exception\n"; 102 | } 103 | 104 | return EXIT_FAILURE; 105 | } 106 | -------------------------------------------------------------------------------- /Chapter06/example2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | using namespace gsl; 27 | 28 | void 29 | redirect_output( 30 | const std::ifstream &is, 31 | const std::ofstream &os, 32 | std::function f) 33 | { 34 | auto cinrdbuf = std::cin.rdbuf(); 35 | auto coutrdbuf = std::cout.rdbuf(); 36 | 37 | std::cin.rdbuf(is.rdbuf()); 38 | std::cout.rdbuf(os.rdbuf()); 39 | 40 | f(); 41 | 42 | std::cin.rdbuf(cinrdbuf); 43 | std::cout.rdbuf(coutrdbuf); 44 | } 45 | 46 | auto 47 | open_streams(cstring_span<> port) 48 | { 49 | std::ifstream is(port.data()); 50 | std::ofstream os(port.data()); 51 | 52 | if (!is || !os) { 53 | std::clog << "ERROR: unable to open serial port:" << port.data() << '\n'; 54 | ::exit(EXIT_FAILURE); 55 | } 56 | 57 | return std::make_pair(std::move(is), std::move(os)); 58 | } 59 | 60 | int 61 | protected_main(int argc, char** argv) 62 | { 63 | auto args = make_span(argv, argc); 64 | 65 | if (argc != 2) { 66 | std::clog << "ERROR: unsupported number of arguments\n"; 67 | ::exit(EXIT_FAILURE); 68 | } 69 | 70 | auto [is, os] = open_streams( 71 | ensure_z(args.at(1)) 72 | ); 73 | 74 | redirect_output(is, os, []{ 75 | std::string buf; 76 | 77 | std::cin >> buf; 78 | std::cout << buf << std::flush; 79 | }); 80 | 81 | return EXIT_SUCCESS; 82 | } 83 | 84 | int 85 | main(int argc, char** argv) 86 | { 87 | try { 88 | return protected_main(argc, argv); 89 | } 90 | catch (const std::exception &e) { 91 | std::cerr << "Caught unhandled exception:\n"; 92 | std::cerr << " - what(): " << e.what() << '\n'; 93 | } 94 | catch (...) { 95 | std::cerr << "Caught unknown exception\n"; 96 | } 97 | 98 | return EXIT_FAILURE; 99 | } 100 | -------------------------------------------------------------------------------- /Chapter07/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter07) 28 | 29 | set(CMAKE_CXX_STANDARD 17) 30 | 31 | # ------------------------------------------------------------------------------ 32 | # Snippets 33 | # ------------------------------------------------------------------------------ 34 | 35 | function(snippet number) 36 | add_executable(snippet${number} scratchpad.cpp) 37 | target_compile_definitions(snippet${number} PRIVATE SNIPPET${number}) 38 | target_link_libraries(snippet${number} rt pthread) 39 | endfunction(snippet) 40 | 41 | snippet(01) 42 | snippet(02) 43 | snippet(03) 44 | snippet(04) 45 | snippet(05) 46 | snippet(06) 47 | snippet(07) 48 | snippet(08) 49 | snippet(09) 50 | snippet(10) 51 | snippet(11) 52 | snippet(12) 53 | snippet(13) 54 | snippet(14) 55 | snippet(15) 56 | snippet(16) 57 | snippet(17) 58 | snippet(18) 59 | snippet(19) 60 | snippet(20) 61 | snippet(21) 62 | snippet(22) 63 | snippet(23) 64 | snippet(24) 65 | snippet(25) 66 | snippet(26) 67 | snippet(27) 68 | snippet(28) 69 | snippet(29) 70 | snippet(30) 71 | snippet(31) 72 | snippet(32) 73 | snippet(33) 74 | snippet(34) 75 | snippet(35) 76 | snippet(36) 77 | snippet(37) 78 | snippet(38) 79 | snippet(39) 80 | snippet(40) 81 | snippet(41) 82 | snippet(42) 83 | snippet(43) 84 | snippet(44) 85 | snippet(45) 86 | snippet(46) 87 | snippet(47) 88 | snippet(48) 89 | snippet(49) 90 | snippet(50) 91 | snippet(51) 92 | snippet(52) 93 | snippet(53) 94 | snippet(54) 95 | snippet(55) 96 | snippet(56) 97 | snippet(57) 98 | snippet(58) 99 | -------------------------------------------------------------------------------- /Chapter08/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter08) 28 | 29 | include(ExternalProject) 30 | find_package(Git REQUIRED) 31 | 32 | set(CMAKE_CXX_FLAGS "-std=c++17") 33 | 34 | # ------------------------------------------------------------------------------ 35 | # Guideline Support Library 36 | # ------------------------------------------------------------------------------ 37 | 38 | list(APPEND GSL_CMAKE_ARGS 39 | -DGSL_TEST=OFF 40 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} 41 | ) 42 | 43 | ExternalProject_Add( 44 | gsl 45 | GIT_REPOSITORY https://github.com/Microsoft/GSL.git 46 | GIT_SHALLOW 1 47 | CMAKE_ARGS ${GSL_CMAKE_ARGS} 48 | PREFIX ${CMAKE_BINARY_DIR}/external/gsl/prefix 49 | TMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/tmp 50 | STAMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/stamp 51 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/gsl/download 52 | SOURCE_DIR ${CMAKE_BINARY_DIR}/external/gsl/src 53 | BINARY_DIR ${CMAKE_BINARY_DIR}/external/gsl/build 54 | UPDATE_DISCONNECTED 1 55 | ) 56 | 57 | # ------------------------------------------------------------------------------ 58 | # Executable 59 | # ------------------------------------------------------------------------------ 60 | 61 | include_directories(${CMAKE_BINARY_DIR}/include) 62 | 63 | add_executable(example1 example1.cpp) 64 | add_dependencies(example1 gsl) 65 | 66 | add_executable(example2 example2.cpp) 67 | add_dependencies(example2 gsl) 68 | 69 | add_executable(example3 example3.cpp) 70 | add_dependencies(example3 gsl) 71 | 72 | # ------------------------------------------------------------------------------ 73 | # Snippets 74 | # ------------------------------------------------------------------------------ 75 | 76 | function(snippet number) 77 | add_executable(snippet${number} scratchpad.cpp) 78 | target_compile_definitions(snippet${number} PRIVATE SNIPPET${number}) 79 | target_link_libraries(snippet${number} stdc++fs) 80 | endfunction(snippet) 81 | 82 | snippet(01) 83 | snippet(02) 84 | snippet(03) 85 | snippet(04) 86 | snippet(05) 87 | snippet(06) 88 | snippet(07) 89 | snippet(08) 90 | snippet(09) 91 | snippet(10) 92 | snippet(11) 93 | snippet(12) 94 | snippet(13) 95 | snippet(14) 96 | #snippet(15) 97 | snippet(16) 98 | snippet(17) 99 | snippet(18) 100 | snippet(19) 101 | snippet(20) 102 | snippet(21) 103 | snippet(22) 104 | snippet(23) 105 | snippet(24) 106 | snippet(25) 107 | snippet(26) 108 | snippet(27) 109 | snippet(28) 110 | snippet(29) 111 | snippet(30) 112 | snippet(31) 113 | snippet(32) 114 | snippet(33) 115 | snippet(34) 116 | snippet(35) 117 | snippet(36) 118 | snippet(37) 119 | snippet(38) 120 | snippet(39) 121 | snippet(40) 122 | snippet(41) 123 | snippet(42) 124 | snippet(43) 125 | snippet(44) 126 | snippet(45) 127 | snippet(46) 128 | # snippet(47) 129 | snippet(48) 130 | snippet(49) 131 | snippet(50) 132 | snippet(51) 133 | snippet(52) 134 | snippet(53) 135 | snippet(54) 136 | snippet(55) 137 | snippet(56) 138 | snippet(57) 139 | snippet(58) 140 | snippet(59) 141 | snippet(60) 142 | snippet(61) 143 | snippet(62) 144 | snippet(63) 145 | snippet(64) 146 | -------------------------------------------------------------------------------- /Chapter08/example1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #ifdef DEBUG_LEVEL 27 | constexpr auto g_debug_level = DEBUG_LEVEL; 28 | #else 29 | constexpr auto g_debug_level = 0; 30 | #endif 31 | 32 | #ifdef NDEBUG 33 | constexpr auto g_ndebug = true; 34 | #else 35 | constexpr auto g_ndebug = false; 36 | #endif 37 | 38 | std::fstream g_log{"log.txt", std::ios::out | std::ios::app}; 39 | 40 | template 41 | constexpr void log(void(*func)()) { 42 | if constexpr (!g_ndebug && (LEVEL <= g_debug_level)) { 43 | std::stringstream buf; 44 | 45 | auto g_buf = std::clog.rdbuf(); 46 | std::clog.rdbuf(buf.rdbuf()); 47 | 48 | func(); 49 | 50 | std::clog.rdbuf(g_buf); 51 | 52 | std::clog << "\033[1;32mDEBUG\033[0m: "; 53 | std::clog << buf.str(); 54 | 55 | g_log << "\033[1;32mDEBUG\033[0m: "; 56 | g_log << buf.str(); 57 | }; 58 | } 59 | 60 | int 61 | protected_main(int argc, char** argv) 62 | { 63 | (void) argc; 64 | (void) argv; 65 | 66 | log<0>([]{ 67 | std::clog << "Hello World\n"; 68 | }); 69 | 70 | std::clog << "Hello World\n"; 71 | 72 | return EXIT_SUCCESS; 73 | } 74 | 75 | int 76 | main(int argc, char** argv) 77 | { 78 | try { 79 | return protected_main(argc, argv); 80 | } 81 | catch (const std::exception &e) { 82 | std::cerr << "Caught unhandled exception:\n"; 83 | std::cerr << " - what(): " << e.what() << '\n'; 84 | } 85 | catch (...) { 86 | std::cerr << "Caught unknown exception\n"; 87 | } 88 | 89 | return EXIT_FAILURE; 90 | } 91 | -------------------------------------------------------------------------------- /Chapter08/example2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | using namespace gsl; 29 | 30 | constexpr auto mode = std::ios::in | std::ios::ate; 31 | 32 | [[noreturn]] void 33 | tail(std::fstream &file) 34 | { 35 | while (true) { 36 | file.peek(); 37 | while(!file.eof()) { 38 | auto pos = file.tellg(); 39 | 40 | std::string buf; 41 | std::getline(file, buf, '\n'); 42 | 43 | if (file.eof() && !file.good()) { 44 | file.seekg(pos); 45 | break; 46 | } 47 | 48 | std::cout << buf << '\n'; 49 | } 50 | 51 | sleep(1); 52 | 53 | file.clear(); 54 | file.sync(); 55 | } 56 | } 57 | 58 | int 59 | protected_main(int argc, char **argv) 60 | { 61 | std::string filename; 62 | auto args = make_span(argv, argc); 63 | 64 | if (args.size() < 2) { 65 | std::cin >> filename; 66 | } 67 | else { 68 | filename = ensure_z(args[1]).data(); 69 | } 70 | 71 | if (auto file = std::fstream(filename, mode)) { 72 | tail(file); 73 | } 74 | 75 | throw std::runtime_error("failed to open file"); 76 | } 77 | 78 | int 79 | main(int argc, char **argv) 80 | { 81 | try { 82 | return protected_main(argc, argv); 83 | } 84 | catch (const std::exception &e) { 85 | std::cerr << "Caught unhandled exception:\n"; 86 | std::cerr << " - what(): " << e.what() << '\n'; 87 | } 88 | catch (...) { 89 | std::cerr << "Caught unknown exception\n"; 90 | } 91 | 92 | return EXIT_FAILURE; 93 | } 94 | -------------------------------------------------------------------------------- /Chapter08/example3.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | constexpr auto size = 0x1000; 31 | 32 | template 33 | auto benchmark(FUNC func) { 34 | auto stime = std::chrono::high_resolution_clock::now(); 35 | func(); 36 | auto etime = std::chrono::high_resolution_clock::now(); 37 | 38 | return etime - stime; 39 | } 40 | 41 | int 42 | protected_main(int argc, char** argv) 43 | { 44 | (void) argc; 45 | (void) argv; 46 | 47 | using namespace std::chrono; 48 | 49 | { 50 | char buf[size] = {}; 51 | if (auto file = std::fstream("test.txt", std::ios::out)) { 52 | file.write(buf, size); 53 | } 54 | } 55 | 56 | { 57 | char buf[size]; 58 | if (auto file = std::fstream("test.txt", std::ios::in)) { 59 | auto time = benchmark([&file, &buf]{ 60 | file.read(buf, size); 61 | }); 62 | 63 | std::cout << "c++ time: " 64 | << duration_cast(time).count() 65 | << '\n'; 66 | } 67 | } 68 | 69 | { 70 | void *buf; 71 | if (int fd = open("test.txt", O_RDONLY); fd != 0) { 72 | auto time = benchmark([&fd, &buf]{ 73 | buf = mmap(NULL, size, PROT_READ, 0, fd, 0); 74 | }); 75 | 76 | munmap(buf, size); 77 | 78 | std::cout << "mmap time: " 79 | << duration_cast(time).count() 80 | << '\n'; 81 | } 82 | } 83 | 84 | return EXIT_SUCCESS; 85 | } 86 | 87 | int 88 | main(int argc, char** argv) 89 | { 90 | try { 91 | return protected_main(argc, argv); 92 | } 93 | catch (const std::exception &e) { 94 | std::cerr << "Caught unhandled exception:\n"; 95 | std::cerr << " - what(): " << e.what() << '\n'; 96 | } 97 | catch (...) { 98 | std::cerr << "Caught unknown exception\n"; 99 | } 100 | 101 | return EXIT_FAILURE; 102 | } 103 | -------------------------------------------------------------------------------- /Chapter09/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter09) 28 | 29 | include(ExternalProject) 30 | find_package(Git REQUIRED) 31 | 32 | set(CMAKE_CXX_STANDARD 17) 33 | 34 | # ------------------------------------------------------------------------------ 35 | # Guideline Support Library 36 | # ------------------------------------------------------------------------------ 37 | 38 | list(APPEND GSL_CMAKE_ARGS 39 | -DGSL_TEST=OFF 40 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} 41 | ) 42 | 43 | ExternalProject_Add( 44 | gsl 45 | GIT_REPOSITORY https://github.com/Microsoft/GSL.git 46 | GIT_SHALLOW 1 47 | CMAKE_ARGS ${GSL_CMAKE_ARGS} 48 | PREFIX ${CMAKE_BINARY_DIR}/external/gsl/prefix 49 | TMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/tmp 50 | STAMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/stamp 51 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/gsl/download 52 | SOURCE_DIR ${CMAKE_BINARY_DIR}/external/gsl/src 53 | BINARY_DIR ${CMAKE_BINARY_DIR}/external/gsl/build 54 | UPDATE_DISCONNECTED 1 55 | ) 56 | 57 | # ------------------------------------------------------------------------------ 58 | # Catch 59 | # ------------------------------------------------------------------------------ 60 | 61 | list(APPEND CATCH_CMAKE_ARGS 62 | -DBUILD_TESTING=OFF 63 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} 64 | ) 65 | 66 | ExternalProject_Add( 67 | catch 68 | GIT_REPOSITORY https://github.com/catchorg/Catch2.git 69 | GIT_SHALLOW 1 70 | CMAKE_ARGS ${CATCH_CMAKE_ARGS} 71 | PREFIX ${CMAKE_BINARY_DIR}/external/catch/prefix 72 | TMP_DIR ${CMAKE_BINARY_DIR}/external/catch/tmp 73 | STAMP_DIR ${CMAKE_BINARY_DIR}/external/catch/stamp 74 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/catch/download 75 | SOURCE_DIR ${CMAKE_BINARY_DIR}/external/catch/src 76 | BINARY_DIR ${CMAKE_BINARY_DIR}/external/catch/build 77 | UPDATE_DISCONNECTED 1 78 | ) 79 | 80 | # ------------------------------------------------------------------------------ 81 | # Executable 82 | # ------------------------------------------------------------------------------ 83 | 84 | include_directories(${CMAKE_BINARY_DIR}/include) 85 | 86 | add_executable(example1 example1.cpp) 87 | add_dependencies(example1 gsl catch) 88 | 89 | add_executable(example2 example2.cpp) 90 | add_dependencies(example2 gsl catch) 91 | 92 | add_executable(example3 example3.cpp) 93 | add_dependencies(example3 gsl catch) 94 | 95 | add_executable(example4 example4.cpp) 96 | add_dependencies(example4 gsl catch) 97 | 98 | add_executable(example5 example5.cpp) 99 | add_dependencies(example5 gsl catch) 100 | 101 | add_executable(example6 example6.cpp) 102 | add_dependencies(example6 gsl catch) 103 | 104 | add_executable(example7 example7.cpp) 105 | add_dependencies(example7 gsl catch) 106 | -------------------------------------------------------------------------------- /Chapter09/example1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | 24 | #define CATCH_CONFIG_MAIN 25 | #include 26 | 27 | // ----------------------------------------------------------------------------- 28 | // Allocator Definition 29 | // ----------------------------------------------------------------------------- 30 | 31 | template 32 | class myallocator 33 | { 34 | public: 35 | 36 | using value_type = T; 37 | using pointer = T *; 38 | using size_type = std::size_t; 39 | 40 | public: 41 | 42 | myallocator() = default; 43 | 44 | template 45 | myallocator(const myallocator &other) noexcept 46 | { (void) other; } 47 | 48 | pointer allocate(size_type n) 49 | { 50 | if (auto ptr = static_cast(malloc(sizeof(T) * n))) { 51 | return ptr; 52 | } 53 | 54 | throw std::bad_alloc(); 55 | } 56 | 57 | void deallocate(pointer p, size_type n) 58 | { (void) n; return free(p); } 59 | }; 60 | 61 | template 62 | bool operator==(const myallocator &, const myallocator &) 63 | { return true; } 64 | 65 | template 66 | bool operator!=(const myallocator &, const myallocator &) 67 | { return false; } 68 | 69 | // ----------------------------------------------------------------------------- 70 | // Tests 71 | // ----------------------------------------------------------------------------- 72 | 73 | TEST_CASE("allocate single object") 74 | { 75 | myallocator myalloc1; 76 | myallocator myalloc2; 77 | 78 | auto ptr = myalloc1.allocate(1); 79 | myalloc2.deallocate(ptr, 1); 80 | } 81 | -------------------------------------------------------------------------------- /Chapter09/example2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #define CATCH_CONFIG_MAIN 28 | #include 29 | 30 | // ----------------------------------------------------------------------------- 31 | // Allocator Definition 32 | // ----------------------------------------------------------------------------- 33 | 34 | template 35 | class myallocator 36 | { 37 | public: 38 | 39 | using value_type = T; 40 | using pointer = T *; 41 | using size_type = std::size_t; 42 | using is_always_equal = std::true_type; 43 | 44 | public: 45 | 46 | myallocator() 47 | { 48 | std::cout << this << " constructor, sizeof(T): " 49 | << sizeof(T) << '\n'; 50 | } 51 | 52 | template 53 | myallocator(const myallocator &other) noexcept 54 | { (void) other; } 55 | 56 | pointer allocate(size_type n) 57 | { 58 | if (auto ptr = static_cast(malloc(sizeof(T) * n))) { 59 | std::cout << this << " A [" << n << "]: " << ptr << '\n'; 60 | return ptr; 61 | } 62 | 63 | throw std::bad_alloc(); 64 | } 65 | 66 | void deallocate(pointer p, size_type n) 67 | { 68 | (void) n; 69 | 70 | std::cout << this << " D [" << n << "]: " << p << '\n'; 71 | free(p); 72 | } 73 | }; 74 | 75 | template 76 | bool operator==(const myallocator &, const myallocator &) 77 | { return true; } 78 | 79 | template 80 | bool operator!=(const myallocator &, const myallocator &) 81 | { return false; } 82 | 83 | // ----------------------------------------------------------------------------- 84 | // Tests 85 | // ----------------------------------------------------------------------------- 86 | 87 | TEST_CASE("constructor / destructor") 88 | { 89 | std::list> mylist; 90 | mylist.emplace_back(42); 91 | } 92 | 93 | // 0x7ffe97b0e8e0 constructor, sizeof(T): 24 94 | // 0x7ffe97b0e8e0 A [1]: 0x55c0793e8580 95 | // 0x7ffe97b0e8e0 D [1]: 0x55c0793e8580 96 | 97 | TEST_CASE("std::vector") 98 | { 99 | std::vector> myvector; 100 | myvector.emplace_back(42); 101 | myvector.emplace_back(42); 102 | myvector.emplace_back(42); 103 | } 104 | 105 | // 0x7ffe1db8e2d0 constructor, sizeof(T): 4 106 | // 0x7ffe1db8e2d0 A [1]: 0x55bf9dbdd550 107 | // 0x7ffe1db8e2d0 A [2]: 0x55bf9dbebe90 108 | // 0x7ffe1db8e2d0 D [1]: 0x55bf9dbdd550 109 | // 0x7ffe1db8e2d0 A [4]: 0x55bf9dbdd550 110 | // 0x7ffe1db8e2d0 D [2]: 0x55bf9dbebe90 111 | // 0x7ffe1db8e2d0 D [4]: 0x55bf9dbdd550 112 | 113 | TEST_CASE("std::deque") 114 | { 115 | std::deque> mydeque; 116 | mydeque.emplace_back(42); 117 | mydeque.emplace_back(42); 118 | mydeque.emplace_back(42); 119 | } 120 | 121 | // 0x7ffdea986f30 constructor, sizeof(T): 4 122 | // 0x7ffdea986e67 A [8]: 0x55d6822b0da0 123 | // 0x7ffdea986f30 A [128]: 0x55d6822afaf0 124 | // 0x7ffdea986f30 D [128]: 0x55d6822afaf0 125 | // 0x7ffdea986e67 D [8]: 0x55d6822b0da0 126 | 127 | TEST_CASE("std::deque many") 128 | { 129 | std::deque> mydeque; 130 | 131 | for (auto i = 0; i< 127; i++) 132 | mydeque.emplace_back(42); 133 | 134 | for (auto i = 0; i< 127; i++) 135 | mydeque.emplace_back(42); 136 | 137 | for (auto i = 0; i< 127; i++) 138 | mydeque.emplace_back(42); 139 | } 140 | 141 | // 0x7ffc5926b280 constructor, sizeof(T): 4 142 | // 0x7ffc5926b1b7 A [8]: 0x560285cc0da0 143 | // 0x7ffc5926b280 A [128]: 0x560285cbfaf0 144 | // 0x7ffc5926b280 A [128]: 0x560285cc1660 145 | // 0x7ffc5926b280 A [128]: 0x560285cc1bc0 146 | // 0x7ffc5926b280 D [128]: 0x560285cbfaf0 147 | // 0x7ffc5926b280 D [128]: 0x560285cc1660 148 | // 0x7ffc5926b280 D [128]: 0x560285cc1bc0 149 | // 0x7ffc5926b1b7 D [8]: 0x560285cc0da0 150 | -------------------------------------------------------------------------------- /Chapter09/example3.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #define CATCH_CONFIG_MAIN 28 | #include 29 | 30 | // ----------------------------------------------------------------------------- 31 | // Allocator Definition 32 | // ----------------------------------------------------------------------------- 33 | 34 | template 35 | class myallocator 36 | { 37 | public: 38 | 39 | using value_type = T; 40 | using pointer = T *; 41 | using size_type = std::size_t; 42 | using is_always_equal = std::true_type; 43 | 44 | public: 45 | 46 | myallocator() 47 | { 48 | std::cout << this << " constructor, sizeof(T): " 49 | << sizeof(T) << '\n'; 50 | } 51 | 52 | template 53 | myallocator(const myallocator &other) noexcept 54 | { (void) other; } 55 | 56 | myallocator(myallocator &&other) noexcept 57 | { 58 | (void) other; 59 | std::cout << this << " move constructor, sizeof(T): " 60 | << sizeof(T) << '\n'; 61 | } 62 | 63 | myallocator &operator=(myallocator &&other) noexcept 64 | { 65 | (void) other; 66 | std::cout << this << " move assignment, sizeof(T): " 67 | << sizeof(T) << '\n'; 68 | return *this; 69 | } 70 | 71 | myallocator(const myallocator &other) noexcept 72 | { 73 | (void) other; 74 | std::cout << this << " copy constructor, sizeof(T): " 75 | << sizeof(T) << '\n'; 76 | } 77 | 78 | myallocator &operator=(const myallocator &other) noexcept 79 | { 80 | (void) other; 81 | std::cout << this << " copy assignment, sizeof(T): " 82 | << sizeof(T) << '\n'; 83 | return *this; 84 | } 85 | 86 | pointer allocate(size_type n) 87 | { 88 | if (auto ptr = static_cast(malloc(sizeof(T) * n))) { 89 | std::cout << this << " A [" << n << "]: " << ptr << '\n'; 90 | return ptr; 91 | } 92 | 93 | throw std::bad_alloc(); 94 | } 95 | 96 | void deallocate(pointer p, size_type n) 97 | { 98 | (void) n; 99 | 100 | std::cout << this << " D [" << n << "]: " << p << '\n'; 101 | free(p); 102 | } 103 | }; 104 | 105 | template 106 | bool operator==(const myallocator &, const myallocator &) 107 | { return true; } 108 | 109 | template 110 | bool operator!=(const myallocator &, const myallocator &) 111 | { return false; } 112 | 113 | // ----------------------------------------------------------------------------- 114 | // Tests 115 | // ----------------------------------------------------------------------------- 116 | 117 | TEST_CASE("copy") 118 | { 119 | std::list> mylist1; 120 | std::list> mylist2; 121 | 122 | mylist1.emplace_back(42); 123 | mylist1.emplace_back(42); 124 | 125 | std::cout << "----------------------------------------\n"; 126 | mylist2 = mylist1; 127 | std::cout << "----------------------------------------\n"; 128 | 129 | mylist2.emplace_back(42); 130 | mylist2.emplace_back(42); 131 | } 132 | 133 | // 0x7fff866d1e50 constructor, sizeof(T): 24 134 | // 0x7fff866d1e70 constructor, sizeof(T): 24 135 | // 0x7fff866d1e50 A [1]: 0x557c430ec550 136 | // 0x7fff866d1e50 A [1]: 0x557c430fae90 137 | // ---------------------------------------- 138 | // 0x7fff866d1d40 copy constructor, sizeof(T): 24 139 | // 0x7fff866d1d40 A [1]: 0x557c430e39a0 140 | // 0x7fff866d1d40 A [1]: 0x557c430f14a0 141 | // ---------------------------------------- 142 | // 0x7fff866d1e70 A [1]: 0x557c430f3b30 143 | // 0x7fff866d1e70 A [1]: 0x557c430ec4d0 144 | // 0x7fff866d1e70 D [1]: 0x557c430e39a0 145 | // 0x7fff866d1e70 D [1]: 0x557c430f14a0 146 | // 0x7fff866d1e70 D [1]: 0x557c430f3b30 147 | // 0x7fff866d1e70 D [1]: 0x557c430ec4d0 148 | // 0x7fff866d1e50 D [1]: 0x557c430ec550 149 | // 0x7fff866d1e50 D [1]: 0x557c430fae90 150 | 151 | TEST_CASE("move") 152 | { 153 | std::list> mylist1; 154 | std::list> mylist2; 155 | 156 | mylist1.emplace_back(42); 157 | mylist1.emplace_back(42); 158 | 159 | std::cout << "----------------------------------------\n"; 160 | mylist2 = std::move(mylist1); 161 | std::cout << "----------------------------------------\n"; 162 | 163 | mylist2.emplace_back(42); 164 | mylist2.emplace_back(42); 165 | } 166 | 167 | // 0x7ffe582e2850 constructor, sizeof(T): 24 168 | // 0x7ffe582e2870 constructor, sizeof(T): 24 169 | // 0x7ffe582e2850 A [1]: 0x56229562d550 170 | // 0x7ffe582e2850 A [1]: 0x56229563be90 171 | // ---------------------------------------- 172 | // ---------------------------------------- 173 | // 0x7ffe582e2870 A [1]: 0x5622956249a0 174 | // 0x7ffe582e2870 A [1]: 0x5622956324a0 175 | // 0x7ffe582e2870 D [1]: 0x56229562d550 176 | // 0x7ffe582e2870 D [1]: 0x56229563be90 177 | // 0x7ffe582e2870 D [1]: 0x5622956249a0 178 | // 0x7ffe582e2870 D [1]: 0x5622956324a0 -------------------------------------------------------------------------------- /Chapter09/example4.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #define CATCH_CONFIG_MAIN 28 | #include 29 | 30 | // ----------------------------------------------------------------------------- 31 | // Allocator Definition 32 | // ----------------------------------------------------------------------------- 33 | 34 | class myallocator_object 35 | { 36 | public: 37 | 38 | using size_type = std::size_t; 39 | 40 | public: 41 | 42 | void *allocate(size_type size) 43 | { 44 | if (auto ptr = malloc(size)) { 45 | std::cout << this << " A " << ptr << '\n'; 46 | return ptr; 47 | } 48 | 49 | throw std::bad_alloc(); 50 | } 51 | 52 | void deallocate(void *ptr) 53 | { 54 | std::cout << this << " D " << ptr << '\n'; 55 | free(ptr); 56 | } 57 | }; 58 | 59 | template 60 | class myallocator 61 | { 62 | public: 63 | 64 | using value_type = T; 65 | using pointer = T *; 66 | using size_type = std::size_t; 67 | using is_always_equal = std::false_type; 68 | 69 | public: 70 | 71 | myallocator() : 72 | m_object{std::make_shared()} 73 | { 74 | std::cout << this << " constructor, sizeof(T): " 75 | << sizeof(T) << '\n'; 76 | } 77 | 78 | template 79 | myallocator(const myallocator &other) noexcept : 80 | m_object{other.m_object} 81 | { 82 | std::cout << this << " copy constructor (U), sizeof(T): " 83 | << sizeof(T) << '\n'; 84 | } 85 | 86 | myallocator(myallocator &&other) noexcept : 87 | m_object{std::move(other.m_object)} 88 | { 89 | std::cout << this << " move constructor, sizeof(T): " 90 | << sizeof(T) << '\n'; 91 | } 92 | 93 | myallocator &operator=(myallocator &&other) noexcept 94 | { 95 | std::cout << this << " move assignment, sizeof(T): " 96 | << sizeof(T) << '\n'; 97 | 98 | m_object = std::move(other.m_object); 99 | return *this; 100 | } 101 | 102 | myallocator(const myallocator &other) noexcept : 103 | m_object{other.m_object} 104 | { 105 | std::cout << this << " copy constructor, sizeof(T): " 106 | << sizeof(T) << '\n'; 107 | } 108 | 109 | myallocator &operator=(const myallocator &other) noexcept 110 | { 111 | std::cout << this << " copy assignment, sizeof(T): " 112 | << sizeof(T) << '\n'; 113 | 114 | m_object = other.m_object; 115 | return *this; 116 | } 117 | 118 | pointer allocate(size_type n) 119 | { 120 | auto ptr = m_object->allocate(sizeof(T) * n); 121 | return static_cast(ptr); 122 | } 123 | 124 | void deallocate(pointer p, size_type n) 125 | { 126 | (void) n; 127 | return m_object->deallocate(p); 128 | } 129 | 130 | private: 131 | 132 | std::shared_ptr m_object; 133 | 134 | template 135 | friend bool operator==(const myallocator &lhs, const myallocator &rhs); 136 | 137 | template 138 | friend bool operator!=(const myallocator &lhs, const myallocator &rhs); 139 | 140 | template 141 | friend class myallocator; 142 | }; 143 | 144 | template 145 | bool operator==(const myallocator &lhs, const myallocator &rhs) 146 | { return lhs.m_object.get() == rhs.m_object.get(); } 147 | 148 | template 149 | bool operator!=(const myallocator &lhs, const myallocator &rhs) 150 | { return lhs.m_object.get() != rhs.m_object.get(); } 151 | 152 | // ----------------------------------------------------------------------------- 153 | // Tests 154 | // ----------------------------------------------------------------------------- 155 | 156 | TEST_CASE("constructor / destructor") 157 | { 158 | std::list> mylist; 159 | mylist.emplace_back(42); 160 | } 161 | 162 | // 0x7ffd65a15ce0 constructor, sizeof(T): 24 163 | // 0x55c4867c3a80 A [1]: 0x55c4867d23b0 164 | // 0x55c4867c3a80 D [1]: 0x55c4867d23b0 165 | 166 | TEST_CASE("copy") 167 | { 168 | std::list> mylist1; 169 | std::list> mylist2; 170 | 171 | mylist1.emplace_back(42); 172 | mylist1.emplace_back(42); 173 | 174 | mylist2.emplace_back(42); 175 | mylist2.emplace_back(42); 176 | 177 | std::cout << "----------------------------------------\n"; 178 | mylist2 = mylist1; 179 | std::cout << "----------------------------------------\n"; 180 | 181 | mylist2.emplace_back(42); 182 | mylist2.emplace_back(42); 183 | } 184 | 185 | // 0x7ffd65a15cb0 constructor, sizeof(T): 24 186 | // 0x7ffd65a15ce0 constructor, sizeof(T): 24 187 | // 0x55c4867c3a80 A [1]: 0x55c4867b9210 188 | // 0x55c4867c3a80 A [1]: 0x55c4867baec0 189 | // 0x55c4867d23c0 A [1]: 0x55c4867c89c0 190 | // 0x55c4867d23c0 A [1]: 0x55c4867cb050 191 | // ---------------------------------------- 192 | // ---------------------------------------- 193 | // 0x55c4867d23c0 A [1]: 0x55c4867c39f0 194 | // 0x55c4867d23c0 A [1]: 0x55c4867c3a10 195 | // 0x55c4867d23c0 D [1]: 0x55c4867c89c0 196 | // 0x55c4867d23c0 D [1]: 0x55c4867cb050 197 | // 0x55c4867d23c0 D [1]: 0x55c4867c39f0 198 | // 0x55c4867d23c0 D [1]: 0x55c4867c3a10 199 | // 0x55c4867c3a80 D [1]: 0x55c4867b9210 200 | // 0x55c4867c3a80 D [1]: 0x55c4867baec0 201 | 202 | TEST_CASE("move") 203 | { 204 | std::list> mylist1; 205 | std::list> mylist2; 206 | 207 | mylist1.emplace_back(42); 208 | mylist1.emplace_back(42); 209 | 210 | mylist2.emplace_back(42); 211 | mylist2.emplace_back(42); 212 | 213 | std::cout << "----------------------------------------\n"; 214 | mylist2 = std::move(mylist1); 215 | std::cout << "----------------------------------------\n"; 216 | 217 | mylist2.emplace_back(42); 218 | mylist2.emplace_back(42); 219 | } 220 | 221 | // 0x7ffd65a15cb0 constructor, sizeof(T): 24 222 | // 0x7ffd65a15ce0 constructor, sizeof(T): 24 223 | // 0x55c4867c3a80 A [1]: 0x55c4867c3a10 224 | // 0x55c4867c3a80 A [1]: 0x55c4867c39f0 225 | // 0x55c4867d23c0 A [1]: 0x55c4867c0170 226 | // 0x55c4867d23c0 A [1]: 0x55c4867c0190 227 | // ---------------------------------------- 228 | // ---------------------------------------- 229 | // 0x55c4867d23c0 A [1]: 0x55c4867b9c90 230 | // 0x55c4867d23c0 A [1]: 0x55c4867b9cb0 231 | // 0x55c4867d23c0 D [1]: 0x55c4867c0170 232 | // 0x55c4867d23c0 D [1]: 0x55c4867c0190 233 | // 0x55c4867d23c0 D [1]: 0x55c4867b9c90 234 | // 0x55c4867d23c0 D [1]: 0x55c4867b9cb0 235 | // 0x55c4867c3a80 D [1]: 0x55c4867c3a10 236 | // 0x55c4867c3a80 D [1]: 0x55c4867c39f0 -------------------------------------------------------------------------------- /Chapter09/example5.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #define CATCH_CONFIG_MAIN 28 | #include 29 | 30 | // ----------------------------------------------------------------------------- 31 | // Allocator Definition 32 | // ----------------------------------------------------------------------------- 33 | 34 | class myallocator_object 35 | { 36 | public: 37 | 38 | using size_type = std::size_t; 39 | 40 | public: 41 | 42 | void *allocate(size_type size) 43 | { 44 | if (auto ptr = malloc(size)) { 45 | std::cout << this << " A " << ptr << '\n'; 46 | return ptr; 47 | } 48 | 49 | throw std::bad_alloc(); 50 | } 51 | 52 | void deallocate(void *ptr) 53 | { 54 | std::cout << this << " D " << ptr << '\n'; 55 | free(ptr); 56 | } 57 | }; 58 | 59 | template 60 | class myallocator 61 | { 62 | public: 63 | 64 | using value_type = T; 65 | using pointer = T *; 66 | using size_type = std::size_t; 67 | using is_always_equal = std::false_type; 68 | using propagate_on_container_copy_assignment = std::true_type; 69 | using propagate_on_container_move_assignment = std::true_type; 70 | using propagate_on_container_swap = std::true_type; 71 | 72 | public: 73 | 74 | myallocator() : 75 | m_object{std::make_shared()} 76 | { 77 | std::cout << this << " constructor, sizeof(T): " 78 | << sizeof(T) << '\n'; 79 | } 80 | 81 | template 82 | myallocator(const myallocator &other) noexcept : 83 | m_object{other.m_object} 84 | { 85 | std::cout << this << " copy constructor (U), sizeof(T): " 86 | << sizeof(T) << '\n'; 87 | } 88 | 89 | myallocator(myallocator &&other) noexcept : 90 | m_object{std::move(other.m_object)} 91 | { 92 | std::cout << this << " move constructor, sizeof(T): " 93 | << sizeof(T) << '\n'; 94 | } 95 | 96 | myallocator &operator=(myallocator &&other) noexcept 97 | { 98 | std::cout << this << " move assignment, sizeof(T): " 99 | << sizeof(T) << '\n'; 100 | 101 | m_object = std::move(other.m_object); 102 | return *this; 103 | } 104 | 105 | myallocator(const myallocator &other) noexcept : 106 | m_object{other.m_object} 107 | { 108 | std::cout << this << " copy constructor, sizeof(T): " 109 | << sizeof(T) << '\n'; 110 | } 111 | 112 | myallocator &operator=(const myallocator &other) noexcept 113 | { 114 | std::cout << this << " copy assignment, sizeof(T): " 115 | << sizeof(T) << '\n'; 116 | 117 | m_object = other.m_object; 118 | return *this; 119 | } 120 | 121 | pointer allocate(size_type n) 122 | { 123 | auto ptr = m_object->allocate(sizeof(T) * n); 124 | return static_cast(ptr); 125 | } 126 | 127 | void deallocate(pointer p, size_type n) 128 | { 129 | (void) n; 130 | return m_object->deallocate(p); 131 | } 132 | 133 | private: 134 | 135 | std::shared_ptr m_object; 136 | 137 | template 138 | friend bool operator==(const myallocator &lhs, const myallocator &rhs); 139 | 140 | template 141 | friend bool operator!=(const myallocator &lhs, const myallocator &rhs); 142 | 143 | template 144 | friend class myallocator; 145 | }; 146 | 147 | template 148 | bool operator==(const myallocator &lhs, const myallocator &rhs) 149 | { return lhs.m_object.get() == rhs.m_object.get(); } 150 | 151 | template 152 | bool operator!=(const myallocator &lhs, const myallocator &rhs) 153 | { return lhs.m_object.get() != rhs.m_object.get(); } 154 | 155 | // ----------------------------------------------------------------------------- 156 | // Tests 157 | // ----------------------------------------------------------------------------- 158 | 159 | TEST_CASE("constructor / destructor") 160 | { 161 | std::list> mylist; 162 | mylist.emplace_back(42); 163 | } 164 | 165 | // 0x7ffce60fbd10 constructor, sizeof(T): 24 166 | // 0x561feb431590 A [1]: 0x561feb43fec0 167 | // 0x561feb431590 D [1]: 0x561feb43fec0 168 | 169 | TEST_CASE("copy") 170 | { 171 | std::list> mylist1; 172 | std::list> mylist2; 173 | 174 | mylist1.emplace_back(42); 175 | mylist1.emplace_back(42); 176 | 177 | mylist2.emplace_back(42); 178 | mylist2.emplace_back(42); 179 | 180 | std::cout << "----------------------------------------\n"; 181 | mylist2 = mylist1; 182 | std::cout << "----------------------------------------\n"; 183 | 184 | mylist2.emplace_back(42); 185 | mylist2.emplace_back(42); 186 | } 187 | 188 | // 0x7ffc766ec580 constructor, sizeof(T): 24 189 | // 0x7ffc766ec5b0 constructor, sizeof(T): 24 190 | // 0x5638419d9720 A [1]: 0x5638419d0b60 191 | // 0x5638419d9720 A [1]: 0x5638419de660 192 | // 0x5638419e8060 A [1]: 0x5638419e0cf0 193 | // 0x5638419e8060 A [1]: 0x5638419d9690 194 | // ---------------------------------------- 195 | // 0x5638419e8060 D [1]: 0x5638419e0cf0 196 | // 0x5638419e8060 D [1]: 0x5638419d9690 197 | // 0x7ffc766ec5b0 copy assignment, sizeof(T): 24 198 | // 0x7ffc766ec450 copy constructor (U), sizeof(T): 4 199 | // 0x7ffc766ec3f0 copy constructor (U), sizeof(T): 24 200 | // 0x7ffc766ec460 copy constructor, sizeof(T): 24 201 | // 0x5638419d9720 A [1]: 0x5638419e8050 202 | // 0x5638419d9720 A [1]: 0x5638419d9690 203 | // ---------------------------------------- 204 | // 0x5638419d9720 A [1]: 0x5638419d96b0 205 | // 0x5638419d9720 A [1]: 0x5638419d5e10 206 | // 0x5638419d9720 D [1]: 0x5638419e8050 207 | // 0x5638419d9720 D [1]: 0x5638419d9690 208 | // 0x5638419d9720 D [1]: 0x5638419d96b0 209 | // 0x5638419d9720 D [1]: 0x5638419d5e10 210 | // 0x5638419d9720 D [1]: 0x5638419d0b60 211 | // 0x5638419d9720 D [1]: 0x5638419de660 212 | 213 | TEST_CASE("move") 214 | { 215 | std::list> mylist1; 216 | std::list> mylist2; 217 | 218 | mylist1.emplace_back(42); 219 | mylist1.emplace_back(42); 220 | 221 | mylist2.emplace_back(42); 222 | mylist2.emplace_back(42); 223 | 224 | std::cout << "----------------------------------------\n"; 225 | mylist2 = std::move(mylist1); 226 | std::cout << "----------------------------------------\n"; 227 | 228 | mylist2.emplace_back(42); 229 | mylist2.emplace_back(42); 230 | } 231 | 232 | // 0x7ffc766ec580 constructor, sizeof(T): 24 233 | // 0x7ffc766ec5b0 constructor, sizeof(T): 24 234 | // 0x5638419d9720 A [1]: 0x5638419d96b0 235 | // 0x5638419d9720 A [1]: 0x5638419d9690 236 | // 0x5638419d5e20 A [1]: 0x5638419e8050 237 | // 0x5638419d5e20 A [1]: 0x5638419d5e30 238 | // ---------------------------------------- 239 | // 0x5638419d5e20 D [1]: 0x5638419e8050 240 | // 0x5638419d5e20 D [1]: 0x5638419d5e30 241 | // 0x7ffc766ec5b0 move assignment, sizeof(T): 24 242 | // ---------------------------------------- 243 | // 0x5638419d9720 A [1]: 0x5638419d5e10 244 | // 0x5638419d9720 A [1]: 0x5638419e8050 245 | // 0x5638419d9720 D [1]: 0x5638419d96b0 246 | // 0x5638419d9720 D [1]: 0x5638419d9690 247 | // 0x5638419d9720 D [1]: 0x5638419d5e10 248 | // 0x5638419d9720 D [1]: 0x5638419e8050 -------------------------------------------------------------------------------- /Chapter09/example6.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #define CATCH_CONFIG_MAIN 27 | #include 28 | 29 | // ----------------------------------------------------------------------------- 30 | // Allocator Definition 31 | // ----------------------------------------------------------------------------- 32 | 33 | template 34 | class myallocator 35 | { 36 | public: 37 | 38 | using value_type = T; 39 | using pointer = T *; 40 | using size_type = std::size_t; 41 | using is_always_equal = std::true_type; 42 | 43 | template struct rebind { 44 | using other = myallocator; 45 | }; 46 | 47 | public: 48 | 49 | myallocator() 50 | { } 51 | 52 | template 53 | myallocator(const myallocator &other) noexcept 54 | { (void) other; } 55 | 56 | pointer allocate(size_type n) 57 | { 58 | if (auto ptr = aligned_alloc(Alignment, sizeof(T) * n)) { 59 | return static_cast(ptr); 60 | } 61 | 62 | throw std::bad_alloc(); 63 | } 64 | 65 | void deallocate(pointer p, size_type n) 66 | { 67 | (void) n; 68 | free(p); 69 | } 70 | }; 71 | 72 | // ----------------------------------------------------------------------------- 73 | // Tests 74 | // ----------------------------------------------------------------------------- 75 | 76 | TEST_CASE("allocate single object") 77 | { 78 | myallocator myalloc; 79 | 80 | auto ptr = myalloc.allocate(1); 81 | std::cout << ptr << '\n'; 82 | myalloc.deallocate(ptr, 1); 83 | } 84 | 85 | // 0x561d512b6500 86 | 87 | TEST_CASE("allocate multiple objects") 88 | { 89 | myallocator myalloc; 90 | 91 | auto ptr = myalloc.allocate(42); 92 | std::cout << ptr << '\n'; 93 | myalloc.deallocate(ptr, 42); 94 | } 95 | 96 | // 0x55dcdcb41500 97 | 98 | TEST_CASE("std::vector single element") 99 | { 100 | std::vector> myvector; 101 | myvector.emplace_back(42); 102 | 103 | std::cout << myvector.data() << '\n'; 104 | } 105 | 106 | // 0x55f875a0f500 107 | -------------------------------------------------------------------------------- /Chapter09/example7.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | 29 | #define CATCH_CONFIG_MAIN 30 | #include 31 | 32 | // ----------------------------------------------------------------------------- 33 | // Pool 34 | // ----------------------------------------------------------------------------- 35 | 36 | class pool 37 | { 38 | public: 39 | 40 | using size_type = std::size_t; 41 | 42 | public: 43 | 44 | pool(size_type size) : 45 | m_size{size} 46 | { } 47 | 48 | void *allocate() 49 | { 50 | if (m_addrs.empty()) { 51 | this->add_addrs(); 52 | } 53 | 54 | auto ptr = m_addrs.top(); 55 | m_addrs.pop(); 56 | 57 | return ptr; 58 | } 59 | 60 | void deallocate(void *ptr) 61 | { m_addrs.push(ptr); } 62 | 63 | void rebind(size_type size) 64 | { 65 | if (!m_addrs.empty() || !m_blocks.empty()) { 66 | std::cerr << "rebind after alloc unsupported\n"; 67 | abort(); 68 | } 69 | 70 | m_size = size; 71 | } 72 | 73 | private: 74 | 75 | void add_addrs() 76 | { 77 | constexpr const auto block_size = 0x1000; 78 | auto block = std::make_unique(block_size); 79 | 80 | auto v = gsl::span( 81 | block.get(), block_size 82 | ); 83 | 84 | auto total_size = 85 | v.size() % m_size == 0 ? v.size() : v.size() - m_size; 86 | 87 | for (auto i = 0; i < total_size; i += m_size) { 88 | m_addrs.push(&v.at(i)); 89 | } 90 | 91 | m_blocks.push(std::move(block)); 92 | } 93 | 94 | private: 95 | 96 | size_type m_size; 97 | 98 | std::stack m_addrs{}; 99 | std::stack> m_blocks{}; 100 | }; 101 | 102 | // ----------------------------------------------------------------------------- 103 | // Allocator 104 | // ----------------------------------------------------------------------------- 105 | 106 | template 107 | class myallocator 108 | { 109 | public: 110 | 111 | using value_type = T; 112 | using pointer = T *; 113 | using size_type = std::size_t; 114 | using is_always_equal = std::false_type; 115 | using propagate_on_container_copy_assignment = std::false_type; 116 | using propagate_on_container_move_assignment = std::true_type; 117 | using propagate_on_container_swap = std::true_type; 118 | 119 | public: 120 | 121 | myallocator() : 122 | m_pool{std::make_shared(sizeof(T))} 123 | { 124 | std::cout << this << " constructor, sizeof(T): " 125 | << sizeof(T) << '\n'; 126 | } 127 | 128 | template 129 | myallocator(const myallocator &other) noexcept : 130 | m_pool{other.m_pool} 131 | { 132 | std::cout << this << " copy constructor (U), sizeof(T): " 133 | << sizeof(T) << '\n'; 134 | 135 | m_pool->rebind(sizeof(T)); 136 | } 137 | 138 | myallocator(myallocator &&other) noexcept : 139 | m_pool{std::move(other.m_pool)} 140 | { 141 | std::cout << this << " move constructor, sizeof(T): " 142 | << sizeof(T) << '\n'; 143 | } 144 | 145 | myallocator &operator=(myallocator &&other) noexcept 146 | { 147 | std::cout << this << " move assignment, sizeof(T): " 148 | << sizeof(T) << '\n'; 149 | 150 | m_pool = std::move(other.m_pool); 151 | return *this; 152 | } 153 | 154 | myallocator(const myallocator &other) noexcept : 155 | m_pool{other.m_pool} 156 | { 157 | std::cout << this << " copy constructor, sizeof(T): " 158 | << sizeof(T) << '\n'; 159 | } 160 | 161 | myallocator &operator=(const myallocator &other) noexcept 162 | { 163 | std::cout << this << " copy assignment, sizeof(T): " 164 | << sizeof(T) << '\n'; 165 | 166 | m_pool = other.m_pool; 167 | return *this; 168 | } 169 | 170 | pointer allocate(size_type n) 171 | { 172 | if (n != 1) { 173 | return static_cast(malloc(sizeof(T) * n)); 174 | } 175 | 176 | return static_cast(m_pool->allocate()); 177 | } 178 | 179 | void deallocate(pointer ptr, size_type n) 180 | { 181 | if (n != 1) { 182 | free(ptr); 183 | } 184 | 185 | m_pool->deallocate(ptr); 186 | } 187 | 188 | private: 189 | 190 | std::shared_ptr m_pool; 191 | 192 | template 193 | friend bool operator==(const myallocator &lhs, const myallocator &rhs); 194 | 195 | template 196 | friend bool operator!=(const myallocator &lhs, const myallocator &rhs); 197 | 198 | template 199 | friend class myallocator; 200 | }; 201 | 202 | template 203 | bool operator==(const myallocator &lhs, const myallocator &rhs) 204 | { return lhs.m_pool.get() == rhs.m_pool.get(); } 205 | 206 | template 207 | bool operator!=(const myallocator &lhs, const myallocator &rhs) 208 | { return lhs.m_pool.get() != rhs.m_pool.get(); } 209 | 210 | // ----------------------------------------------------------------------------- 211 | // Tests 212 | // ----------------------------------------------------------------------------- 213 | 214 | template 215 | auto benchmark(FUNC func) { 216 | auto stime = std::chrono::high_resolution_clock::now(); 217 | func(); 218 | auto etime = std::chrono::high_resolution_clock::now(); 219 | 220 | return (etime - stime).count(); 221 | } 222 | 223 | TEST_CASE("compare add many") 224 | { 225 | constexpr const auto num = 100000; 226 | 227 | std::list mylist1; 228 | std::list> mylist2; 229 | 230 | auto time1 = benchmark([&]{ 231 | for (auto i = 0; i < num; i++) { 232 | mylist1.emplace_back(42); 233 | } 234 | }); 235 | 236 | auto time2 = benchmark([&]{ 237 | for (auto i = 0; i < num; i++) { 238 | mylist2.emplace_back(42); 239 | } 240 | }); 241 | 242 | std::cout << "[TEST] add many:\n"; 243 | std::cout << " - time1: " << time1 << '\n'; 244 | std::cout << " - time2: " << time2 << '\n'; 245 | } 246 | 247 | // 0x7ffca71d7a00 constructor, sizeof(T): 24 248 | // [TEST] add many: 249 | // - time1: 3921793 250 | // - time2: 1787499 251 | 252 | TEST_CASE("compare remove many") 253 | { 254 | constexpr const auto num = 100000; 255 | 256 | std::list mylist1; 257 | std::list> mylist2; 258 | 259 | for (auto i = 0; i < num; i++) { 260 | mylist1.emplace_back(42); 261 | mylist2.emplace_back(42); 262 | } 263 | 264 | auto time1 = benchmark([&]{ 265 | for (auto i = 0; i < num; i++) { 266 | mylist1.pop_front(); 267 | } 268 | }); 269 | 270 | auto time2 = benchmark([&]{ 271 | for (auto i = 0; i < num; i++) { 272 | mylist2.pop_front(); 273 | } 274 | }); 275 | 276 | std::cout << "[TEST] remove many:\n"; 277 | std::cout << " - time1: " << time1 << '\n'; 278 | std::cout << " - time2: " << time2 << '\n'; 279 | } 280 | 281 | TEST_CASE("std::list verify") 282 | { 283 | constexpr const auto num = 100000; 284 | 285 | std::list> mylist; 286 | 287 | for (auto i = 0; i < num; i++) { 288 | mylist.emplace_back(i); 289 | } 290 | 291 | uint64_t total1{}; 292 | uint64_t total2{}; 293 | 294 | for (auto i = 0; i < num; i++) { 295 | total1 += i; 296 | total2 += mylist.back(); 297 | mylist.pop_back(); 298 | } 299 | 300 | std::cout << "[TEST] verify: "; 301 | if (total1 == total2) { 302 | std::cout << "success\n"; 303 | } 304 | else { 305 | std::cout << "failure\n"; 306 | std::cout << " - total1: " << total1 << '\n'; 307 | std::cout << " - total2: " << total2 << '\n'; 308 | } 309 | } 310 | -------------------------------------------------------------------------------- /Chapter10/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter10) 28 | 29 | include(ExternalProject) 30 | find_package(Git REQUIRED) 31 | 32 | set(CMAKE_CXX_STANDARD 17) 33 | 34 | # ------------------------------------------------------------------------------ 35 | # Guideline Support Library 36 | # ------------------------------------------------------------------------------ 37 | 38 | list(APPEND GSL_CMAKE_ARGS 39 | -DGSL_TEST=OFF 40 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} 41 | ) 42 | 43 | ExternalProject_Add( 44 | gsl 45 | GIT_REPOSITORY https://github.com/Microsoft/GSL.git 46 | GIT_SHALLOW 1 47 | CMAKE_ARGS ${GSL_CMAKE_ARGS} 48 | PREFIX ${CMAKE_BINARY_DIR}/external/gsl/prefix 49 | TMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/tmp 50 | STAMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/stamp 51 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/gsl/download 52 | SOURCE_DIR ${CMAKE_BINARY_DIR}/external/gsl/src 53 | BINARY_DIR ${CMAKE_BINARY_DIR}/external/gsl/build 54 | UPDATE_DISCONNECTED 1 55 | ) 56 | 57 | # ------------------------------------------------------------------------------ 58 | # JSON 59 | # ------------------------------------------------------------------------------ 60 | 61 | list(APPEND JSON_CMAKE_ARGS 62 | -DBUILD_TESTING=OFF 63 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} 64 | ) 65 | 66 | ExternalProject_Add( 67 | json 68 | GIT_REPOSITORY https://github.com/nlohmann/json.git 69 | GIT_SHALLOW 1 70 | CMAKE_ARGS ${JSON_CMAKE_ARGS} 71 | PREFIX ${CMAKE_BINARY_DIR}/external/json/prefix 72 | TMP_DIR ${CMAKE_BINARY_DIR}/external/json/tmp 73 | STAMP_DIR ${CMAKE_BINARY_DIR}/external/json/stamp 74 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/json/download 75 | SOURCE_DIR ${CMAKE_BINARY_DIR}/external/json/src 76 | BINARY_DIR ${CMAKE_BINARY_DIR}/external/json/build 77 | UPDATE_DISCONNECTED 1 78 | ) 79 | 80 | # ------------------------------------------------------------------------------ 81 | # Executable 82 | # ------------------------------------------------------------------------------ 83 | 84 | include_directories(${CMAKE_BINARY_DIR}/include) 85 | 86 | add_executable(example1_server example1.cpp) 87 | target_compile_definitions(example1_server PUBLIC SERVER=1) 88 | add_dependencies(example1_server gsl json) 89 | 90 | add_executable(example1_client example1.cpp) 91 | target_compile_definitions(example1_client PUBLIC CLIENT=1) 92 | add_dependencies(example1_client gsl json) 93 | 94 | add_executable(example2_server example2.cpp) 95 | target_compile_definitions(example2_server PUBLIC SERVER=1) 96 | add_dependencies(example2_server gsl json) 97 | 98 | add_executable(example2_client example2.cpp) 99 | target_compile_definitions(example2_client PUBLIC CLIENT=1) 100 | add_dependencies(example2_client gsl json) 101 | 102 | add_executable(example3_server example3.cpp) 103 | target_compile_definitions(example3_server PUBLIC SERVER=1) 104 | add_dependencies(example3_server gsl json) 105 | 106 | add_executable(example3_client example3.cpp) 107 | target_compile_definitions(example3_client PUBLIC CLIENT=1) 108 | add_dependencies(example3_client gsl json) 109 | 110 | add_executable(example4_server example4.cpp) 111 | target_compile_definitions(example4_server PUBLIC SERVER=1) 112 | add_dependencies(example4_server gsl json) 113 | 114 | add_executable(example4_client example4.cpp) 115 | target_compile_definitions(example4_client PUBLIC CLIENT=1) 116 | add_dependencies(example4_client gsl json) 117 | 118 | add_executable(example5_server example5.cpp) 119 | target_compile_definitions(example5_server PUBLIC SERVER=1) 120 | add_dependencies(example5_server gsl json) 121 | 122 | add_executable(example5_client example5.cpp) 123 | target_compile_definitions(example5_client PUBLIC CLIENT=1) 124 | add_dependencies(example5_client gsl json) 125 | -------------------------------------------------------------------------------- /Chapter10/example1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #define PORT 22000 23 | #define MAX_SIZE 0x10 24 | 25 | #ifdef SERVER 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | class myserver 38 | { 39 | int m_fd{}; 40 | struct sockaddr_in m_addr{}; 41 | struct sockaddr_in m_client{}; 42 | 43 | public: 44 | explicit myserver(uint16_t port) 45 | { 46 | if (m_fd = ::socket(AF_INET, SOCK_DGRAM, 0); m_fd == -1) { 47 | throw std::runtime_error(strerror(errno)); 48 | } 49 | 50 | m_addr.sin_family = AF_INET; 51 | m_addr.sin_port = htons(port); 52 | m_addr.sin_addr.s_addr = htonl(INADDR_ANY); 53 | 54 | if (this->bind() == -1) { 55 | throw std::runtime_error(strerror(errno)); 56 | } 57 | } 58 | 59 | int bind() 60 | { 61 | return ::bind( 62 | m_fd, 63 | reinterpret_cast(&m_addr), 64 | sizeof(m_addr) 65 | ); 66 | } 67 | 68 | ssize_t recv(std::array &buf) 69 | { 70 | socklen_t client_len = sizeof(m_client); 71 | 72 | return ::recvfrom( 73 | m_fd, 74 | buf.data(), 75 | buf.size(), 76 | 0, 77 | (struct sockaddr *) &m_client, 78 | &client_len 79 | ); 80 | } 81 | 82 | ssize_t send(std::array &buf, ssize_t len) 83 | { 84 | if (len >= buf.size()) { 85 | throw std::out_of_range("len >= buf.size()"); 86 | } 87 | 88 | return ::sendto( 89 | m_fd, 90 | buf.data(), 91 | len, 92 | 0, 93 | (struct sockaddr *) &m_client, 94 | sizeof(m_client) 95 | ); 96 | } 97 | 98 | void echo() 99 | { 100 | while(true) 101 | { 102 | std::array buf{}; 103 | 104 | if (auto len = recv(buf); len != 0) { 105 | send(buf, len); 106 | } 107 | else { 108 | break; 109 | } 110 | } 111 | } 112 | 113 | ~myserver() 114 | { 115 | close(m_fd); 116 | } 117 | }; 118 | 119 | int 120 | protected_main(int argc, char** argv) 121 | { 122 | (void) argc; 123 | (void) argv; 124 | 125 | myserver server{PORT}; 126 | server.echo(); 127 | 128 | return EXIT_SUCCESS; 129 | } 130 | 131 | int 132 | main(int argc, char** argv) 133 | { 134 | try { 135 | return protected_main(argc, argv); 136 | } 137 | catch (const std::exception &e) { 138 | std::cerr << "Caught unhandled exception:\n"; 139 | std::cerr << " - what(): " << e.what() << '\n'; 140 | } 141 | catch (...) { 142 | std::cerr << "Caught unknown exception\n"; 143 | } 144 | 145 | return EXIT_FAILURE; 146 | } 147 | 148 | #endif 149 | 150 | #ifdef CLIENT 151 | 152 | #include 153 | #include 154 | #include 155 | #include 156 | 157 | #include 158 | #include 159 | 160 | #include 161 | #include 162 | 163 | class myclient 164 | { 165 | int m_fd{}; 166 | struct sockaddr_in m_addr{}; 167 | 168 | public: 169 | explicit myclient(uint16_t port) 170 | { 171 | if (m_fd = ::socket(AF_INET, SOCK_DGRAM, 0); m_fd == -1) { 172 | throw std::runtime_error(strerror(errno)); 173 | } 174 | 175 | m_addr.sin_family = AF_INET; 176 | m_addr.sin_port = htons(port); 177 | m_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 178 | 179 | if (connect() == -1) { 180 | throw std::runtime_error(strerror(errno)); 181 | } 182 | } 183 | 184 | int connect() 185 | { 186 | return ::connect( 187 | m_fd, 188 | reinterpret_cast(&m_addr), 189 | sizeof(m_addr) 190 | ); 191 | } 192 | 193 | ssize_t send(const std::string &buf) 194 | { 195 | return ::send( 196 | m_fd, 197 | buf.data(), 198 | buf.size(), 199 | 0 200 | ); 201 | } 202 | 203 | ssize_t recv(std::array &buf) 204 | { 205 | return ::recv( 206 | m_fd, 207 | buf.data(), 208 | buf.size() - 1, 209 | 0 210 | ); 211 | } 212 | 213 | void echo() 214 | { 215 | while(true) { 216 | std::string sendbuf{}; 217 | std::array recvbuf{}; 218 | 219 | std::cin >> sendbuf; 220 | if (sendbuf == "exit") { 221 | send({}); 222 | break; 223 | } 224 | 225 | send(sendbuf); 226 | recv(recvbuf); 227 | 228 | std::cout << recvbuf.data() << '\n'; 229 | } 230 | } 231 | 232 | ~myclient() 233 | { 234 | close(m_fd); 235 | } 236 | }; 237 | 238 | int 239 | protected_main(int argc, char** argv) 240 | { 241 | (void) argc; 242 | (void) argv; 243 | 244 | myclient client{PORT}; 245 | client.echo(); 246 | 247 | return EXIT_SUCCESS; 248 | } 249 | 250 | int 251 | main(int argc, char** argv) 252 | { 253 | try { 254 | return protected_main(argc, argv); 255 | } 256 | catch (const std::exception &e) { 257 | std::cerr << "Caught unhandled exception:\n"; 258 | std::cerr << " - what(): " << e.what() << '\n'; 259 | } 260 | catch (...) { 261 | std::cerr << "Caught unknown exception\n"; 262 | } 263 | 264 | return EXIT_FAILURE; 265 | } 266 | 267 | #endif 268 | -------------------------------------------------------------------------------- /Chapter10/example2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #define PORT 22000 23 | #define MAX_SIZE 0x10 24 | 25 | #ifdef SERVER 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | class myserver 38 | { 39 | int m_fd{}; 40 | int m_client{}; 41 | struct sockaddr_in m_addr{}; 42 | 43 | public: 44 | 45 | explicit myserver(uint16_t port) 46 | { 47 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 48 | throw std::runtime_error(strerror(errno)); 49 | } 50 | 51 | m_addr.sin_family = AF_INET; 52 | m_addr.sin_port = htons(port); 53 | m_addr.sin_addr.s_addr = htonl(INADDR_ANY); 54 | 55 | if (this->bind() == -1) { 56 | throw std::runtime_error(strerror(errno)); 57 | } 58 | } 59 | 60 | int bind() 61 | { 62 | return ::bind( 63 | m_fd, 64 | reinterpret_cast(&m_addr), 65 | sizeof(m_addr) 66 | ); 67 | } 68 | 69 | ssize_t recv(std::array &buf) 70 | { 71 | return ::recv( 72 | m_client, 73 | buf.data(), 74 | buf.size(), 75 | 0 76 | ); 77 | } 78 | 79 | ssize_t send(std::array &buf, ssize_t len) 80 | { 81 | if (len >= buf.size()) { 82 | throw std::out_of_range("len >= buf.size()"); 83 | } 84 | 85 | return ::send( 86 | m_client, 87 | buf.data(), 88 | len, 89 | 0 90 | ); 91 | } 92 | 93 | void echo() 94 | { 95 | if (::listen(m_fd, 0) == -1) { 96 | throw std::runtime_error(strerror(errno)); 97 | } 98 | 99 | if (m_client = ::accept(m_fd, nullptr, nullptr); m_client == -1) { 100 | throw std::runtime_error(strerror(errno)); 101 | } 102 | 103 | while(true) 104 | { 105 | std::array buf{}; 106 | 107 | if (auto len = recv(buf); len != 0) { 108 | send(buf, len); 109 | } 110 | else { 111 | break; 112 | } 113 | } 114 | 115 | close(m_client); 116 | } 117 | 118 | ~myserver() 119 | { 120 | close(m_fd); 121 | } 122 | }; 123 | 124 | int 125 | protected_main(int argc, char** argv) 126 | { 127 | (void) argc; 128 | (void) argv; 129 | 130 | myserver server{PORT}; 131 | server.echo(); 132 | 133 | return EXIT_SUCCESS; 134 | } 135 | 136 | int 137 | main(int argc, char** argv) 138 | { 139 | try { 140 | return protected_main(argc, argv); 141 | } 142 | catch (const std::exception &e) { 143 | std::cerr << "Caught unhandled exception:\n"; 144 | std::cerr << " - what(): " << e.what() << '\n'; 145 | } 146 | catch (...) { 147 | std::cerr << "Caught unknown exception\n"; 148 | } 149 | 150 | return EXIT_FAILURE; 151 | } 152 | 153 | #endif 154 | 155 | #ifdef CLIENT 156 | 157 | #include 158 | #include 159 | #include 160 | #include 161 | 162 | #include 163 | #include 164 | 165 | #include 166 | #include 167 | 168 | class myclient 169 | { 170 | int m_fd{}; 171 | struct sockaddr_in m_addr{}; 172 | 173 | public: 174 | 175 | explicit myclient(uint16_t port) 176 | { 177 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 178 | throw std::runtime_error(strerror(errno)); 179 | } 180 | 181 | m_addr.sin_family = AF_INET; 182 | m_addr.sin_port = htons(port); 183 | m_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 184 | 185 | if (connect() == -1) { 186 | throw std::runtime_error(strerror(errno)); 187 | } 188 | } 189 | 190 | int connect() 191 | { 192 | return ::connect( 193 | m_fd, 194 | reinterpret_cast(&m_addr), 195 | sizeof(m_addr) 196 | ); 197 | } 198 | 199 | ssize_t send(const std::string &buf) 200 | { 201 | return ::send( 202 | m_fd, 203 | buf.data(), 204 | buf.size(), 205 | 0 206 | ); 207 | } 208 | 209 | ssize_t recv(std::array &buf) 210 | { 211 | return ::recv( 212 | m_fd, 213 | buf.data(), 214 | buf.size() - 1, 215 | 0 216 | ); 217 | } 218 | 219 | void echo() 220 | { 221 | while(true) { 222 | std::string sendbuf{}; 223 | std::array recvbuf{}; 224 | 225 | std::cin >> sendbuf; 226 | 227 | send(sendbuf); 228 | recv(recvbuf); 229 | 230 | std::cout << recvbuf.data() << '\n'; 231 | } 232 | } 233 | 234 | ~myclient() 235 | { 236 | close(m_fd); 237 | } 238 | }; 239 | 240 | int 241 | protected_main(int argc, char** argv) 242 | { 243 | (void) argc; 244 | (void) argv; 245 | 246 | myclient client{PORT}; 247 | client.echo(); 248 | 249 | return EXIT_SUCCESS; 250 | } 251 | 252 | int 253 | main(int argc, char** argv) 254 | { 255 | try { 256 | return protected_main(argc, argv); 257 | } 258 | catch (const std::exception &e) { 259 | std::cerr << "Caught unhandled exception:\n"; 260 | std::cerr << " - what(): " << e.what() << '\n'; 261 | } 262 | catch (...) { 263 | std::cerr << "Caught unknown exception\n"; 264 | } 265 | 266 | return EXIT_FAILURE; 267 | } 268 | 269 | #endif 270 | 271 | class mysocket 272 | { 273 | public: 274 | mysocket(uint16_t port) 275 | { 276 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 277 | throw std::runtime_error(strerror(errno)); 278 | } 279 | } 280 | 281 | ~mysocket() 282 | { 283 | close(m_fd); 284 | } 285 | 286 | auto descriptor() const 287 | { return m_fd; } 288 | 289 | private: 290 | 291 | int m_fd{}; 292 | }; 293 | -------------------------------------------------------------------------------- /Chapter10/example3.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #define PORT 22000 23 | #define MAX_SIZE 0x1000 24 | 25 | #ifdef SERVER 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | std::fstream g_log{"server_log.txt", std::ios::out | std::ios::app}; 41 | 42 | class myserver 43 | { 44 | int m_fd{}; 45 | int m_client{}; 46 | struct sockaddr_in m_addr{}; 47 | 48 | public: 49 | 50 | explicit myserver(uint16_t port) 51 | { 52 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 53 | throw std::runtime_error(strerror(errno)); 54 | } 55 | 56 | m_addr.sin_family = AF_INET; 57 | m_addr.sin_port = htons(port); 58 | m_addr.sin_addr.s_addr = htonl(INADDR_ANY); 59 | 60 | if (this->bind() == -1) { 61 | throw std::runtime_error(strerror(errno)); 62 | } 63 | } 64 | 65 | int bind() 66 | { 67 | return ::bind( 68 | m_fd, 69 | reinterpret_cast(&m_addr), 70 | sizeof(m_addr) 71 | ); 72 | } 73 | 74 | ssize_t recv(std::array &buf) 75 | { 76 | return ::recv( 77 | m_client, 78 | buf.data(), 79 | buf.size(), 80 | 0 81 | ); 82 | } 83 | 84 | void log() 85 | { 86 | if (::listen(m_fd, 0) == -1) { 87 | throw std::runtime_error(strerror(errno)); 88 | } 89 | 90 | if (m_client = ::accept(m_fd, nullptr, nullptr); m_client == -1) { 91 | throw std::runtime_error(strerror(errno)); 92 | } 93 | 94 | while(true) 95 | { 96 | std::array buf{}; 97 | 98 | if (auto len = recv(buf); len != 0) { 99 | g_log.write(buf.data(), len); 100 | std::clog.write(buf.data(), len); 101 | } 102 | else { 103 | break; 104 | } 105 | } 106 | 107 | close(m_client); 108 | } 109 | 110 | ~myserver() 111 | { 112 | close(m_fd); 113 | } 114 | }; 115 | 116 | int 117 | protected_main(int argc, char** argv) 118 | { 119 | (void) argc; 120 | (void) argv; 121 | 122 | myserver server{PORT}; 123 | server.log(); 124 | 125 | return EXIT_SUCCESS; 126 | } 127 | 128 | int 129 | main(int argc, char** argv) 130 | { 131 | try { 132 | return protected_main(argc, argv); 133 | } 134 | catch (const std::exception &e) { 135 | std::cerr << "Caught unhandled exception:\n"; 136 | std::cerr << " - what(): " << e.what() << '\n'; 137 | } 138 | catch (...) { 139 | std::cerr << "Caught unknown exception\n"; 140 | } 141 | 142 | return EXIT_FAILURE; 143 | } 144 | 145 | #endif 146 | 147 | #ifdef CLIENT 148 | 149 | #include 150 | #include 151 | #include 152 | 153 | #include 154 | #include 155 | #include 156 | 157 | #include 158 | #include 159 | 160 | #include 161 | #include 162 | 163 | #ifdef DEBUG_LEVEL 164 | constexpr auto g_debug_level = DEBUG_LEVEL; 165 | #else 166 | constexpr auto g_debug_level = 0; 167 | #endif 168 | 169 | #ifdef NDEBUG 170 | constexpr auto g_ndebug = true; 171 | #else 172 | constexpr auto g_ndebug = false; 173 | #endif 174 | 175 | class myclient 176 | { 177 | int m_fd{}; 178 | struct sockaddr_in m_addr{}; 179 | 180 | public: 181 | explicit myclient(uint16_t port) 182 | { 183 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 184 | throw std::runtime_error(strerror(errno)); 185 | } 186 | 187 | m_addr.sin_family = AF_INET; 188 | m_addr.sin_port = htons(port); 189 | m_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 190 | 191 | if (connect() == -1) { 192 | throw std::runtime_error(strerror(errno)); 193 | } 194 | } 195 | 196 | int connect() 197 | { 198 | return ::connect( 199 | m_fd, 200 | reinterpret_cast(&m_addr), 201 | sizeof(m_addr) 202 | ); 203 | } 204 | 205 | ssize_t send(const std::string &buf) 206 | { 207 | return ::send( 208 | m_fd, 209 | buf.data(), 210 | buf.size(), 211 | 0 212 | ); 213 | } 214 | 215 | ~myclient() 216 | { 217 | close(m_fd); 218 | } 219 | }; 220 | 221 | myclient g_client{PORT}; 222 | std::fstream g_log{"client_log.txt", std::ios::out | std::ios::app}; 223 | 224 | template 225 | constexpr void log(void(*func)()) { 226 | if constexpr (!g_ndebug && (LEVEL <= g_debug_level)) { 227 | std::stringstream buf; 228 | 229 | auto g_buf = std::clog.rdbuf(); 230 | std::clog.rdbuf(buf.rdbuf()); 231 | 232 | func(); 233 | 234 | std::clog.rdbuf(g_buf); 235 | 236 | std::clog << "\033[1;32mDEBUG\033[0m: "; 237 | std::clog << buf.str(); 238 | 239 | g_log << "\033[1;32mDEBUG\033[0m: "; 240 | g_log << buf.str(); 241 | 242 | g_client.send("\033[1;32mDEBUG\033[0m: "); 243 | g_client.send(buf.str()); 244 | }; 245 | } 246 | 247 | int 248 | protected_main(int argc, char** argv) 249 | { 250 | (void) argc; 251 | (void) argv; 252 | 253 | log<0>([]{ 254 | std::clog << "Hello World\n"; 255 | }); 256 | 257 | std::clog << "Hello World\n"; 258 | 259 | return EXIT_SUCCESS; 260 | } 261 | 262 | int 263 | main(int argc, char** argv) 264 | { 265 | try { 266 | return protected_main(argc, argv); 267 | } 268 | catch (const std::exception &e) { 269 | std::cerr << "Caught unhandled exception:\n"; 270 | std::cerr << " - what(): " << e.what() << '\n'; 271 | } 272 | catch (...) { 273 | std::cerr << "Caught unknown exception\n"; 274 | } 275 | 276 | return EXIT_FAILURE; 277 | } 278 | 279 | #endif 280 | -------------------------------------------------------------------------------- /Chapter10/example4.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | 24 | #define PORT 22000 25 | #define MAX_SIZE 0x1000 26 | 27 | struct packet 28 | { 29 | uint64_t data1; 30 | uint64_t data2; 31 | 32 | uint64_t len; 33 | char buf[MAX_SIZE]; 34 | }; 35 | 36 | #ifdef SERVER 37 | 38 | #include 39 | #include 40 | 41 | #include 42 | #include 43 | 44 | #include 45 | #include 46 | 47 | class myserver 48 | { 49 | public: 50 | 51 | explicit myserver(uint16_t port) 52 | { 53 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 54 | throw std::runtime_error(strerror(errno)); 55 | } 56 | 57 | m_addr.sin_family = AF_INET; 58 | m_addr.sin_port = htons(port); 59 | m_addr.sin_addr.s_addr = htonl(INADDR_ANY); 60 | 61 | if (this->bind() == -1) { 62 | throw std::runtime_error(strerror(errno)); 63 | } 64 | } 65 | 66 | ~myserver() 67 | { 68 | close(m_fd); 69 | } 70 | 71 | int bind() 72 | { 73 | return ::bind( 74 | m_fd, 75 | reinterpret_cast(&m_addr), 76 | sizeof(m_addr) 77 | ); 78 | } 79 | 80 | ssize_t recv(packet &p) 81 | { 82 | return ::recv( 83 | m_client, 84 | &p, 85 | sizeof(p), 86 | 0 87 | ); 88 | } 89 | 90 | void recv_packet() 91 | { 92 | if (::listen(m_fd, 0) == -1) { 93 | throw std::runtime_error(strerror(errno)); 94 | } 95 | 96 | if (m_client = ::accept(m_fd, nullptr, nullptr); m_client == -1) { 97 | throw std::runtime_error(strerror(errno)); 98 | } 99 | 100 | packet p{}; 101 | 102 | if (auto len = recv(p); len != 0) { 103 | auto msg = std::string(p.buf, p.len); 104 | 105 | std::cout << "data1: " << p.data1 << '\n'; 106 | std::cout << "data2: " << p.data2 << '\n'; 107 | std::cout << "msg: \"" << msg << "\"\n"; 108 | std::cout << "len: " << len << '\n'; 109 | } 110 | 111 | close(m_client); 112 | } 113 | 114 | private: 115 | 116 | int m_fd{}; 117 | int m_client{}; 118 | struct sockaddr_in m_addr{}; 119 | }; 120 | 121 | int 122 | protected_main(int argc, char** argv) 123 | { 124 | (void) argc; 125 | (void) argv; 126 | 127 | myserver server{PORT}; 128 | server.recv_packet(); 129 | 130 | return EXIT_SUCCESS; 131 | } 132 | 133 | int 134 | main(int argc, char** argv) 135 | { 136 | try { 137 | return protected_main(argc, argv); 138 | } 139 | catch (const std::exception &e) { 140 | std::cerr << "Caught unhandled exception:\n"; 141 | std::cerr << " - what(): " << e.what() << '\n'; 142 | } 143 | catch (...) { 144 | std::cerr << "Caught unknown exception\n"; 145 | } 146 | 147 | return EXIT_FAILURE; 148 | } 149 | 150 | #endif 151 | 152 | #ifdef CLIENT 153 | 154 | #include 155 | #include 156 | #include 157 | 158 | #include 159 | #include 160 | 161 | #include 162 | #include 163 | 164 | class myclient 165 | { 166 | public: 167 | explicit myclient(uint16_t port) 168 | { 169 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 170 | throw std::runtime_error(strerror(errno)); 171 | } 172 | 173 | m_addr.sin_family = AF_INET; 174 | m_addr.sin_port = htons(port); 175 | m_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 176 | 177 | if (connect() == -1) { 178 | throw std::runtime_error(strerror(errno)); 179 | } 180 | } 181 | 182 | ~myclient() 183 | { 184 | close(m_fd); 185 | } 186 | 187 | int connect() 188 | { 189 | return ::connect( 190 | m_fd, 191 | reinterpret_cast(&m_addr), 192 | sizeof(m_addr) 193 | ); 194 | } 195 | 196 | ssize_t send(const packet &p) 197 | { 198 | return ::send( 199 | m_fd, 200 | &p, 201 | sizeof(p), 202 | 0 203 | ); 204 | } 205 | 206 | void send_packet() 207 | { 208 | auto msg = std::string("Hello World"); 209 | 210 | packet p = { 211 | 42, 212 | 43, 213 | msg.size(), 214 | {} 215 | }; 216 | 217 | memcpy(p.buf, msg.data(), msg.size()); 218 | 219 | send(p); 220 | } 221 | 222 | private: 223 | 224 | int m_fd{}; 225 | struct sockaddr_in m_addr{}; 226 | }; 227 | 228 | 229 | int 230 | protected_main(int argc, char** argv) 231 | { 232 | (void) argc; 233 | (void) argv; 234 | 235 | myclient client{PORT}; 236 | client.send_packet(); 237 | 238 | return EXIT_SUCCESS; 239 | } 240 | 241 | int 242 | main(int argc, char** argv) 243 | { 244 | try { 245 | return protected_main(argc, argv); 246 | } 247 | catch (const std::exception &e) { 248 | std::cerr << "Caught unhandled exception:\n"; 249 | std::cerr << " - what(): " << e.what() << '\n'; 250 | } 251 | catch (...) { 252 | std::cerr << "Caught unknown exception\n"; 253 | } 254 | 255 | return EXIT_FAILURE; 256 | } 257 | 258 | #endif 259 | -------------------------------------------------------------------------------- /Chapter10/example5.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #define PORT 22000 23 | #define MAX_SIZE 0x1000 24 | 25 | #ifdef SERVER 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | #include 37 | using json = nlohmann::json; 38 | 39 | class myserver 40 | { 41 | public: 42 | 43 | explicit myserver(uint16_t port) 44 | { 45 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 46 | throw std::runtime_error(strerror(errno)); 47 | } 48 | 49 | m_addr.sin_family = AF_INET; 50 | m_addr.sin_port = htons(port); 51 | m_addr.sin_addr.s_addr = htonl(INADDR_ANY); 52 | 53 | if (this->bind() == -1) { 54 | throw std::runtime_error(strerror(errno)); 55 | } 56 | } 57 | 58 | ~myserver() 59 | { 60 | close(m_fd); 61 | } 62 | 63 | int bind() 64 | { 65 | return ::bind( 66 | m_fd, 67 | reinterpret_cast(&m_addr), 68 | sizeof(m_addr) 69 | ); 70 | } 71 | 72 | ssize_t recv(std::array &buf) 73 | { 74 | return ::recv( 75 | m_client, 76 | buf.data(), 77 | buf.size(), 78 | 0 79 | ); 80 | } 81 | 82 | void recv_packet() 83 | { 84 | std::array buf{}; 85 | 86 | if (::listen(m_fd, 0) == -1) { 87 | throw std::runtime_error(strerror(errno)); 88 | } 89 | 90 | if (m_client = ::accept(m_fd, nullptr, nullptr); m_client == -1) { 91 | throw std::runtime_error(strerror(errno)); 92 | } 93 | 94 | if (auto len = recv(buf); len != 0) { 95 | auto j = json::parse(buf.data(), buf.data() + len); 96 | 97 | std::cout << "data1: " << j["data1"] << '\n'; 98 | std::cout << "data2: " << j["data2"] << '\n'; 99 | std::cout << "msg: " << j["msg"] << '\n'; 100 | std::cout << "len: " << len << '\n'; 101 | } 102 | 103 | close(m_client); 104 | } 105 | 106 | private: 107 | 108 | int m_fd{}; 109 | int m_client{}; 110 | struct sockaddr_in m_addr{}; 111 | }; 112 | 113 | int 114 | protected_main(int argc, char** argv) 115 | { 116 | (void) argc; 117 | (void) argv; 118 | 119 | myserver server{PORT}; 120 | server.recv_packet(); 121 | 122 | return EXIT_SUCCESS; 123 | } 124 | 125 | int 126 | main(int argc, char** argv) 127 | { 128 | try { 129 | return protected_main(argc, argv); 130 | } 131 | catch (const std::exception &e) { 132 | std::cerr << "Caught unhandled exception:\n"; 133 | std::cerr << " - what(): " << e.what() << '\n'; 134 | } 135 | catch (...) { 136 | std::cerr << "Caught unknown exception\n"; 137 | } 138 | 139 | return EXIT_FAILURE; 140 | } 141 | 142 | #endif 143 | 144 | #ifdef CLIENT 145 | 146 | #include 147 | #include 148 | #include 149 | 150 | #include 151 | #include 152 | 153 | #include 154 | #include 155 | 156 | #include 157 | using json = nlohmann::json; 158 | 159 | class myclient 160 | { 161 | public: 162 | explicit myclient(uint16_t port) 163 | { 164 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 165 | throw std::runtime_error(strerror(errno)); 166 | } 167 | 168 | m_addr.sin_family = AF_INET; 169 | m_addr.sin_port = htons(port); 170 | m_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 171 | 172 | if (connect() == -1) { 173 | throw std::runtime_error(strerror(errno)); 174 | } 175 | } 176 | 177 | ~myclient() 178 | { 179 | close(m_fd); 180 | } 181 | 182 | int connect() 183 | { 184 | return ::connect( 185 | m_fd, 186 | reinterpret_cast(&m_addr), 187 | sizeof(m_addr) 188 | ); 189 | } 190 | 191 | ssize_t send(const std::string &str) 192 | { 193 | return ::send( 194 | m_fd, 195 | str.data(), 196 | str.size(), 197 | 0 198 | ); 199 | } 200 | 201 | void send_packet() 202 | { 203 | json j; 204 | 205 | j["data1"] = 42; 206 | j["data2"] = 43; 207 | j["msg"] = "Hello World"; 208 | 209 | send(j.dump()); 210 | } 211 | 212 | private: 213 | 214 | int m_fd{}; 215 | struct sockaddr_in m_addr{}; 216 | }; 217 | 218 | 219 | int 220 | protected_main(int argc, char** argv) 221 | { 222 | (void) argc; 223 | (void) argv; 224 | 225 | myclient client{PORT}; 226 | client.send_packet(); 227 | 228 | return EXIT_SUCCESS; 229 | } 230 | 231 | int 232 | main(int argc, char** argv) 233 | { 234 | try { 235 | return protected_main(argc, argv); 236 | } 237 | catch (const std::exception &e) { 238 | std::cerr << "Caught unhandled exception:\n"; 239 | std::cerr << " - what(): " << e.what() << '\n'; 240 | } 241 | catch (...) { 242 | std::cerr << "Caught unknown exception\n"; 243 | } 244 | 245 | return EXIT_FAILURE; 246 | } 247 | 248 | #endif 249 | -------------------------------------------------------------------------------- /Chapter11/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter11) 28 | 29 | include(ExternalProject) 30 | find_package(Git REQUIRED) 31 | 32 | set(CMAKE_CXX_STANDARD 17) 33 | 34 | # ------------------------------------------------------------------------------ 35 | # Guideline Support Library 36 | # ------------------------------------------------------------------------------ 37 | 38 | list(APPEND GSL_CMAKE_ARGS 39 | -DGSL_TEST=OFF 40 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} 41 | ) 42 | 43 | ExternalProject_Add( 44 | gsl 45 | GIT_REPOSITORY https://github.com/Microsoft/GSL.git 46 | GIT_SHALLOW 1 47 | CMAKE_ARGS ${GSL_CMAKE_ARGS} 48 | PREFIX ${CMAKE_BINARY_DIR}/external/gsl/prefix 49 | TMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/tmp 50 | STAMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/stamp 51 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/gsl/download 52 | SOURCE_DIR ${CMAKE_BINARY_DIR}/external/gsl/src 53 | BINARY_DIR ${CMAKE_BINARY_DIR}/external/gsl/build 54 | ) 55 | 56 | # ------------------------------------------------------------------------------ 57 | # Executable 58 | # ------------------------------------------------------------------------------ 59 | 60 | include_directories(${CMAKE_BINARY_DIR}/include) 61 | 62 | add_executable(example1 example1.cpp) 63 | add_dependencies(example1 gsl) 64 | 65 | add_executable(example2 example2.cpp) 66 | add_dependencies(example2 gsl) 67 | 68 | # ------------------------------------------------------------------------------ 69 | # Snippets 70 | # ------------------------------------------------------------------------------ 71 | 72 | function(snippet number) 73 | add_executable(snippet${number} scratchpad.cpp) 74 | target_compile_definitions(snippet${number} PRIVATE SNIPPET${number}) 75 | endfunction(snippet) 76 | 77 | snippet(01) 78 | snippet(02) 79 | snippet(03) 80 | snippet(04) 81 | snippet(05) 82 | snippet(06) 83 | snippet(07) 84 | snippet(08) 85 | snippet(09) 86 | snippet(10) 87 | snippet(11) 88 | snippet(12) 89 | snippet(13) 90 | snippet(14) 91 | snippet(15) 92 | snippet(16) 93 | snippet(17) 94 | snippet(18) 95 | snippet(19) 96 | snippet(20) 97 | snippet(21) 98 | snippet(22) 99 | snippet(23) 100 | -------------------------------------------------------------------------------- /Chapter11/example1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | 29 | using namespace std::chrono; 30 | 31 | template 32 | std::ostream & 33 | operator<<(std::ostream &os, std::chrono::time_point &obj) 34 | { 35 | auto t = std::chrono::system_clock::to_time_t(obj); 36 | return os << ctime(&t); 37 | } 38 | 39 | int 40 | protected_main(int argc, char **argv) 41 | { 42 | using namespace std::chrono; 43 | auto args = gsl::make_span(argv, argc); 44 | 45 | if (args.size() != 2) { 46 | std::cerr << "wrong number of arguments\n"; 47 | ::exit(1); 48 | } 49 | 50 | gsl::cstring_span<> arg = gsl::ensure_z(args.at(1)); 51 | 52 | while(true) { 53 | auto now = std::chrono::system_clock::now(); 54 | std::cout << "time: " << now; 55 | 56 | sleep(std::stoi(arg.data())); 57 | } 58 | } 59 | 60 | int 61 | main(int argc, char **argv) 62 | { 63 | try { 64 | return protected_main(argc, argv); 65 | } 66 | catch (const std::exception &e) { 67 | std::cerr << "Caught unhandled exception:\n"; 68 | std::cerr << " - what(): " << e.what() << '\n'; 69 | } 70 | catch (...) { 71 | std::cerr << "Caught unknown exception\n"; 72 | } 73 | 74 | return EXIT_FAILURE; 75 | } 76 | -------------------------------------------------------------------------------- /Chapter11/example2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | 27 | template 28 | auto benchmark(FUNC func) { 29 | auto stime = std::chrono::high_resolution_clock::now(); 30 | func(); 31 | auto etime = std::chrono::high_resolution_clock::now(); 32 | 33 | return etime - stime; 34 | } 35 | 36 | int 37 | protected_main(int argc, char **argv) 38 | { 39 | using namespace std::chrono; 40 | 41 | auto args = gsl::make_span(argv, argc); 42 | 43 | if (args.size() != 2) { 44 | std::cerr << "wrong number of arguments\n"; 45 | ::exit(1); 46 | } 47 | 48 | gsl::cstring_span<> arg = gsl::ensure_z(args.at(1)); 49 | 50 | auto d = benchmark([&arg]{ 51 | for (uint64_t i = 0; i < std::stoi(arg.data()); i++); 52 | }); 53 | 54 | std::cout << "time: " << 55 | duration_cast(d).count() << '\n'; 56 | 57 | std::cout << "time: " << 58 | duration_cast(d).count() << '\n'; 59 | 60 | std::cout << "time: " << 61 | duration_cast(d).count() << '\n'; 62 | } 63 | 64 | int 65 | main(int argc, char **argv) 66 | { 67 | try { 68 | return protected_main(argc, argv); 69 | } 70 | catch (const std::exception &e) { 71 | std::cerr << "Caught unhandled exception:\n"; 72 | std::cerr << " - what(): " << e.what() << '\n'; 73 | } 74 | catch (...) { 75 | std::cerr << "Caught unknown exception\n"; 76 | } 77 | 78 | return EXIT_FAILURE; 79 | } 80 | -------------------------------------------------------------------------------- /Chapter11/scratchpad.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | // ----------------------------------------------------------------------------- 23 | // Section: Stream Based IO 24 | // ----------------------------------------------------------------------------- 25 | 26 | #if SNIPPET01 27 | 28 | #include 29 | #include 30 | 31 | int main() 32 | { 33 | auto t = time(nullptr); 34 | std::cout << "time: " << t << '\n'; 35 | } 36 | 37 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 38 | // time: 1531603643 39 | 40 | #endif 41 | 42 | #if SNIPPET02 43 | 44 | #include 45 | #include 46 | 47 | int main() 48 | { 49 | time_t t; 50 | time(&t); 51 | std::cout << "time: " << t << '\n'; 52 | } 53 | 54 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 55 | // time: 1531603652 56 | 57 | #endif 58 | 59 | #if SNIPPET03 60 | 61 | #include 62 | #include 63 | 64 | int main() 65 | { 66 | auto t = time(nullptr); 67 | std::cout << "time: " << ctime(&t); 68 | } 69 | 70 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 71 | // time: Sat Jul 14 15:27:44 2018 72 | 73 | #endif 74 | 75 | #if SNIPPET05 76 | 77 | #include 78 | #include 79 | 80 | int main() 81 | { 82 | auto t = time(nullptr); 83 | std::cout << "time: " << asctime(localtime(&t)); 84 | } 85 | 86 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 87 | // time: Sat Jul 14 15:28:59 2018 88 | 89 | #endif 90 | 91 | #if SNIPPET06 92 | 93 | #include 94 | #include 95 | 96 | int main() 97 | { 98 | auto t = time(nullptr); 99 | std::cout << "time: " << asctime(gmtime(&t)); 100 | } 101 | 102 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 103 | // time: Sat Jul 14 21:46:12 2018 104 | 105 | #endif 106 | 107 | #if SNIPPET07 108 | 109 | #include 110 | #include 111 | 112 | int main() 113 | { 114 | auto t = time(nullptr); 115 | 116 | char buf[256]{}; 117 | strftime(buf, sizeof(buf), "%m/%d/%Y", localtime(&t)); 118 | 119 | std::cout << "time: " << buf << '\n'; 120 | } 121 | 122 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 123 | // time: 07/14/2018 124 | 125 | #endif 126 | 127 | #if SNIPPET08 128 | 129 | #include 130 | #include 131 | 132 | int main() 133 | { 134 | auto t = time(nullptr); 135 | 136 | char buf[256]{}; 137 | strftime(buf, sizeof(buf), "%H:%M", localtime(&t)); 138 | 139 | std::cout << "time: " << buf << '\n'; 140 | } 141 | 142 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 143 | // time: 15:41 144 | 145 | #endif 146 | 147 | #if SNIPPET09 148 | 149 | #include 150 | #include 151 | 152 | int main() 153 | { 154 | auto t = time(nullptr); 155 | 156 | char buf[256]{}; 157 | strftime(buf, sizeof(buf), "%a %b %d %H:%M:%S %Y", localtime(&t)); 158 | 159 | std::cout << "time: " << buf << '\n'; 160 | } 161 | 162 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 163 | // time: Sat Jul 14 15:44:57 2018 164 | 165 | #endif 166 | 167 | #if SNIPPET10 168 | 169 | #include 170 | #include 171 | 172 | #include 173 | 174 | int main() 175 | { 176 | auto t1 = time(nullptr); 177 | sleep(2); 178 | auto t2 = time(nullptr); 179 | 180 | std::cout << "diff: " << difftime(t2, t1) << '\n'; 181 | std::cout << "diff: " << t2 - t1 << '\n'; 182 | } 183 | 184 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 185 | // diff: 2 186 | 187 | #endif 188 | 189 | #if SNIPPET11 190 | 191 | #include 192 | #include 193 | 194 | int main() 195 | { 196 | auto t1 = time(nullptr); 197 | auto lt = localtime(&t1); 198 | auto t2 = mktime(lt); 199 | 200 | std::cout << "time: " << ctime(&t2); 201 | } 202 | 203 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 204 | // time: Sat Jul 14 16:00:13 2018 205 | 206 | #endif 207 | 208 | #if SNIPPET12 209 | 210 | #include 211 | #include 212 | 213 | int main() 214 | { 215 | std::cout << "clock: " << clock() << '\n'; 216 | } 217 | 218 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 219 | // clock: 2002 220 | 221 | #endif 222 | 223 | #if SNIPPET13 224 | 225 | #include 226 | #include 227 | 228 | #include 229 | 230 | int main() 231 | { 232 | auto c1 = clock(); 233 | sleep(2); 234 | auto c2 = clock(); 235 | 236 | std::cout << "clock: " << 237 | static_cast(c2 - c1) / CLOCKS_PER_SEC << '\n'; 238 | } 239 | 240 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 241 | // clock: 3.2e-05 242 | 243 | #endif 244 | 245 | #if SNIPPET04 246 | 247 | #include 248 | #include 249 | 250 | #include 251 | 252 | int main() 253 | { 254 | auto c1 = clock(); 255 | 256 | auto t1 = time(nullptr); 257 | while(time(nullptr) - t1 <= 2); 258 | 259 | auto c2 = clock(); 260 | 261 | std::cout << "clock: " << 262 | static_cast(c2 - c1) / CLOCKS_PER_SEC << '\n'; 263 | } 264 | 265 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 266 | // clock: 2.05336 267 | 268 | #endif 269 | 270 | #if SNIPPET14 271 | 272 | #include 273 | #include 274 | 275 | int main() 276 | { 277 | auto t = std::chrono::system_clock::now(); 278 | std::cout << "time: " << std::chrono::system_clock::to_time_t(t) << '\n'; 279 | } 280 | 281 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 282 | // time: 1531606644 283 | 284 | #endif 285 | 286 | #if SNIPPET15 287 | 288 | #include 289 | #include 290 | 291 | template 292 | std::ostream & 293 | operator<<(std::ostream &os, std::chrono::time_point &obj) 294 | { 295 | auto t = std::chrono::system_clock::to_time_t(obj); 296 | return os << ctime(&t); 297 | } 298 | 299 | int main() 300 | { 301 | auto now = std::chrono::system_clock::now(); 302 | std::cout << "time: " << now; 303 | } 304 | 305 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 306 | // time: Sat Jul 14 19:01:55 2018 307 | 308 | #endif 309 | 310 | #if SNIPPET16 311 | 312 | #include 313 | #include 314 | 315 | using namespace std::chrono; 316 | 317 | template 318 | std::ostream & 319 | operator<<(std::ostream &os, std::chrono::time_point &obj) 320 | { 321 | auto t = std::chrono::system_clock::to_time_t(obj); 322 | return os << ctime(&t); 323 | } 324 | 325 | int main() 326 | { 327 | auto now = std::chrono::system_clock::now(); 328 | 329 | std::cout << "time: " << now; 330 | 331 | now += 1h; 332 | std::cout << "time: " << now; 333 | 334 | now -= 1h; 335 | std::cout << "time: " << now; 336 | } 337 | 338 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 339 | // time: 1531606644 340 | 341 | #endif 342 | 343 | #if SNIPPET17 344 | 345 | #include 346 | #include 347 | 348 | int main() 349 | { 350 | auto now1 = std::chrono::system_clock::now(); 351 | auto now2 = std::chrono::system_clock::now(); 352 | 353 | std::cout << std::boolalpha; 354 | std::cout << "compare: " << (now1 < now2) << '\n'; 355 | std::cout << "compare: " << (now1 > now2) << '\n'; 356 | std::cout << "compare: " << (now1 <= now2) << '\n'; 357 | std::cout << "compare: " << (now1 >= now2) << '\n'; 358 | std::cout << "compare: " << (now1 == now2) << '\n'; 359 | std::cout << "compare: " << (now1 != now2) << '\n'; 360 | } 361 | 362 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 363 | // compare: true 364 | // compare: false 365 | // compare: true 366 | // compare: false 367 | // compare: false 368 | // compare: true 369 | 370 | #endif 371 | 372 | #if SNIPPET18 373 | 374 | #include 375 | #include 376 | 377 | #include 378 | 379 | int main() 380 | { 381 | using namespace std::chrono; 382 | 383 | auto now1 = system_clock::now(); 384 | sleep(2); 385 | auto now2 = system_clock::now(); 386 | 387 | std::cout << "time: " << 388 | duration_cast(now2 - now1).count() << '\n'; 389 | 390 | std::cout << "time: " << 391 | duration_cast(now2 - now1).count() << '\n'; 392 | 393 | std::cout << "time: " << 394 | duration_cast(now2 - now1).count() << '\n'; 395 | } 396 | 397 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 398 | // time: 2 399 | // time: 2001 400 | // time: 2001415132 401 | 402 | #endif 403 | 404 | #if SNIPPET19 405 | 406 | #include 407 | #include 408 | 409 | int main() 410 | { 411 | using namespace std::chrono; 412 | 413 | seconds t(42); 414 | 415 | t++; 416 | std::cout << "time: " << t.count() << '\n'; 417 | 418 | t--; 419 | std::cout << "time: " << t.count() << '\n'; 420 | 421 | t += 1s; 422 | std::cout << "time: " << t.count() << '\n'; 423 | 424 | t -= 1s; 425 | std::cout << "time: " << t.count() << '\n'; 426 | 427 | t %= 2s; 428 | std::cout << "time: " << t.count() << '\n'; 429 | } 430 | 431 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 432 | // time: 43 433 | // time: 42 434 | // time: 43 435 | // time: 42 436 | // time: 0 437 | 438 | #endif 439 | 440 | #if SNIPPET20 441 | 442 | #include 443 | #include 444 | 445 | int main() 446 | { 447 | using namespace std::chrono; 448 | 449 | auto t1 = 0s; 450 | auto t2 = 42s; 451 | 452 | std::cout << std::boolalpha; 453 | std::cout << "compare: " << (t1 < t2) << '\n'; 454 | std::cout << "compare: " << (t1 > t2) << '\n'; 455 | std::cout << "compare: " << (t1 <= t2) << '\n'; 456 | std::cout << "compare: " << (t1 >= t2) << '\n'; 457 | std::cout << "compare: " << (t1 == t2) << '\n'; 458 | std::cout << "compare: " << (t1 != t2) << '\n'; 459 | } 460 | 461 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 462 | // compare: true 463 | // compare: false 464 | // compare: true 465 | // compare: false 466 | // compare: false 467 | // compare: true 468 | 469 | #endif 470 | 471 | #if SNIPPET21 472 | 473 | #include 474 | #include 475 | 476 | int main() 477 | { 478 | using namespace std::chrono; 479 | 480 | auto s1 = -42001ms; 481 | 482 | std::cout << "floor: " << floor(s1).count() << '\n'; 483 | std::cout << "ceil: " << ceil(s1).count() << '\n'; 484 | std::cout << "round: " << round(s1).count() << '\n'; 485 | std::cout << "abs: " << abs(s1).count() << '\n'; 486 | } 487 | 488 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 489 | // floor: -43 490 | // ceil: -42 491 | // round: -42 492 | // abs: 42001 493 | 494 | #endif 495 | 496 | #if SNIPPET22 497 | 498 | #include 499 | #include 500 | 501 | #include 502 | 503 | int main() 504 | { 505 | using namespace std::chrono; 506 | 507 | auto now1 = steady_clock::now(); 508 | sleep(2); 509 | auto now2 = steady_clock::now(); 510 | 511 | std::cout << "time: " << 512 | duration_cast(now2 - now1).count() << '\n'; 513 | 514 | std::cout << "time: " << 515 | duration_cast(now2 - now1).count() << '\n'; 516 | 517 | std::cout << "time: " << 518 | duration_cast(now2 - now1).count() << '\n'; 519 | } 520 | 521 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 522 | // time: 2 523 | // time: 2001 524 | // time: 2001447628 525 | 526 | #endif 527 | 528 | #if SNIPPET23 529 | 530 | #include 531 | #include 532 | 533 | #include 534 | 535 | int main() 536 | { 537 | using namespace std::chrono; 538 | 539 | auto now1 = high_resolution_clock::now(); 540 | sleep(2); 541 | auto now2 = high_resolution_clock::now(); 542 | 543 | std::cout << "time: " << 544 | duration_cast(now2 - now1).count() << '\n'; 545 | 546 | std::cout << "time: " << 547 | duration_cast(now2 - now1).count() << '\n'; 548 | 549 | std::cout << "time: " << 550 | duration_cast(now2 - now1).count() << '\n'; 551 | } 552 | 553 | // > g++ -std=c++17 scratchpad.cpp; ./a.out 554 | // time: 2 555 | // time: 2000 556 | // time: 2002297281 557 | 558 | #endif 559 | -------------------------------------------------------------------------------- /Chapter12/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter12) 28 | 29 | include(ExternalProject) 30 | find_package(Git REQUIRED) 31 | 32 | set(CMAKE_CXX_STANDARD 17) 33 | 34 | # ------------------------------------------------------------------------------ 35 | # Guideline Support Library 36 | # ------------------------------------------------------------------------------ 37 | 38 | list(APPEND GSL_CMAKE_ARGS 39 | -DGSL_TEST=OFF 40 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} 41 | ) 42 | 43 | ExternalProject_Add( 44 | gsl 45 | GIT_REPOSITORY https://github.com/Microsoft/GSL.git 46 | GIT_SHALLOW 1 47 | CMAKE_ARGS ${GSL_CMAKE_ARGS} 48 | PREFIX ${CMAKE_BINARY_DIR}/external/gsl/prefix 49 | TMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/tmp 50 | STAMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/stamp 51 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/gsl/download 52 | SOURCE_DIR ${CMAKE_BINARY_DIR}/external/gsl/src 53 | BINARY_DIR ${CMAKE_BINARY_DIR}/external/gsl/build 54 | UPDATE_DISCONNECTED 1 55 | ) 56 | 57 | # ------------------------------------------------------------------------------ 58 | # Executable 59 | # ------------------------------------------------------------------------------ 60 | 61 | include_directories(${CMAKE_BINARY_DIR}/include) 62 | 63 | add_executable(example1 example1.cpp) 64 | add_dependencies(example1 gsl) 65 | target_link_libraries(example1 pthread) 66 | 67 | add_executable(example2 example2.cpp) 68 | add_dependencies(example2 gsl) 69 | target_link_libraries(example2 pthread) 70 | 71 | add_executable(example3_server example3.cpp) 72 | target_compile_definitions(example3_server PUBLIC SERVER=1) 73 | add_dependencies(example3_server gsl) 74 | target_link_libraries(example3_server pthread) 75 | 76 | add_executable(example3_client example3.cpp) 77 | target_compile_definitions(example3_client PUBLIC CLIENT=1) 78 | add_dependencies(example3_client gsl) 79 | target_link_libraries(example3_client pthread) 80 | 81 | # ------------------------------------------------------------------------------ 82 | # Snippets 83 | # ------------------------------------------------------------------------------ 84 | 85 | function(snippet number) 86 | add_executable(snippet${number} scratchpad.cpp) 87 | target_compile_definitions(snippet${number} PRIVATE SNIPPET${number}) 88 | target_link_libraries(snippet${number} pthread) 89 | endfunction(snippet) 90 | 91 | snippet(01) 92 | snippet(02) 93 | snippet(03) 94 | snippet(04) 95 | snippet(05) 96 | snippet(06) 97 | snippet(07) 98 | snippet(08) 99 | snippet(09) 100 | snippet(10) 101 | snippet(11) 102 | snippet(12) 103 | snippet(13) 104 | snippet(14) 105 | snippet(15) 106 | snippet(16) 107 | snippet(17) 108 | snippet(18) 109 | snippet(19) 110 | snippet(20) 111 | snippet(21) 112 | snippet(22) 113 | snippet(23) 114 | snippet(24) 115 | snippet(25) 116 | snippet(26) 117 | snippet(27) 118 | snippet(28) 119 | -------------------------------------------------------------------------------- /Chapter12/example1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | using namespace gsl; 30 | 31 | using namespace std::string_literals; 32 | 33 | class primes 34 | { 35 | std::list m_primes; 36 | mutable std::mutex m_mutex; 37 | 38 | public: 39 | 40 | void add(int prime) 41 | { 42 | std::unique_lock lock(m_mutex); 43 | m_primes.push_back(prime); 44 | } 45 | 46 | void print() 47 | { 48 | std::unique_lock lock(m_mutex); 49 | m_primes.sort(); 50 | 51 | for (const auto prime : m_primes) { 52 | std::cout << prime << ' '; 53 | } 54 | 55 | std::cout << '\n'; 56 | } 57 | }; 58 | 59 | primes g_primes; 60 | 61 | void check_prime(int num) 62 | { 63 | for (auto i = 2; i < num; i++) { 64 | if (num % i == 0) { 65 | return; 66 | } 67 | } 68 | 69 | g_primes.add(num); 70 | } 71 | 72 | int 73 | protected_main(int argc, char** argv) 74 | { 75 | auto args = make_span(argv, argc); 76 | 77 | if (args.size() != 4) { 78 | std::cerr << "wrong number of arguments\n"; 79 | ::exit(1); 80 | } 81 | 82 | int max_prime = std::stoi(args.at(1)); 83 | int max_threads = std::stoi(args.at(2)); 84 | 85 | if (max_prime < 3) { 86 | std::cerr << "max_prime must be 2 or more\n"; 87 | ::exit(1); 88 | } 89 | 90 | if (max_threads < 1) { 91 | std::cerr << "max_threads must be 1 or more\n"; 92 | ::exit(1); 93 | } 94 | 95 | for (auto i = 2; i < max_prime; i += max_threads) { 96 | 97 | std::list threads; 98 | for (auto t = 0; t < max_threads; t++) { 99 | threads.push_back(std::thread{check_prime, i + t}); 100 | } 101 | 102 | for (auto &thread : threads) { 103 | thread.join(); 104 | } 105 | } 106 | 107 | if (args.at(3) == "print"s) { 108 | g_primes.print(); 109 | } 110 | 111 | return EXIT_SUCCESS; 112 | } 113 | 114 | int 115 | main(int argc, char** argv) 116 | { 117 | try { 118 | return protected_main(argc, argv); 119 | } 120 | catch (const std::exception &e) { 121 | std::cerr << "Caught unhandled exception:\n"; 122 | std::cerr << " - what(): " << e.what() << '\n'; 123 | } 124 | catch (...) { 125 | std::cerr << "Caught unknown exception\n"; 126 | } 127 | 128 | return EXIT_FAILURE; 129 | } 130 | -------------------------------------------------------------------------------- /Chapter12/example2.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | using namespace gsl; 29 | 30 | int count = 0; 31 | bool enable_counter = true; 32 | 33 | std::mutex mutex; 34 | std::condition_variable cond; 35 | 36 | void tick() 37 | { 38 | cond.notify_one(); 39 | 40 | while (enable_counter) { 41 | count++; 42 | } 43 | } 44 | 45 | template 46 | auto timer(FUNC func) { 47 | std::thread timer{tick}; 48 | 49 | std::unique_lock lock(mutex); 50 | cond.wait(lock); 51 | 52 | func(); 53 | 54 | enable_counter = false; 55 | timer.join(); 56 | 57 | return count; 58 | } 59 | 60 | int 61 | protected_main(int argc, char** argv) 62 | { 63 | auto args = make_span(argv, argc); 64 | 65 | if (args.size() != 2) { 66 | std::cerr << "wrong number of arguments\n"; 67 | ::exit(1); 68 | } 69 | 70 | auto ticks = timer([&] { 71 | for (auto i = 0; i < std::stoi(args.at(1)); i++) { 72 | } 73 | }); 74 | 75 | std::cout << "ticks: " << ticks << '\n'; 76 | 77 | return EXIT_SUCCESS; 78 | } 79 | 80 | int 81 | main(int argc, char** argv) 82 | { 83 | try { 84 | return protected_main(argc, argv); 85 | } 86 | catch (const std::exception &e) { 87 | std::cerr << "Caught unhandled exception:\n"; 88 | std::cerr << " - what(): " << e.what() << '\n'; 89 | } 90 | catch (...) { 91 | std::cerr << "Caught unknown exception\n"; 92 | } 93 | 94 | return EXIT_FAILURE; 95 | } 96 | -------------------------------------------------------------------------------- /Chapter12/example3.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #define PORT 22000 23 | #define MAX_SIZE 0x1000 24 | 25 | #ifdef SERVER 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | 43 | std::mutex log_mutex; 44 | std::fstream g_log{"server_log.txt", std::ios::out | std::ios::app}; 45 | 46 | ssize_t 47 | recv(int handle, std::array &buf) 48 | { 49 | return ::recv( 50 | handle, 51 | buf.data(), 52 | buf.size(), 53 | 0 54 | ); 55 | } 56 | 57 | void 58 | log(int handle) 59 | { 60 | while(true) 61 | { 62 | std::array buf{}; 63 | 64 | if (auto len = recv(handle, buf); len != 0) { 65 | std::unique_lock lock(log_mutex); 66 | 67 | g_log.write(buf.data(), len); 68 | std::clog.write(buf.data(), len); 69 | 70 | g_log.flush(); 71 | } 72 | else { 73 | break; 74 | } 75 | } 76 | 77 | close(handle); 78 | } 79 | 80 | class myserver 81 | { 82 | int m_fd{}; 83 | struct sockaddr_in m_addr{}; 84 | 85 | public: 86 | 87 | myserver(uint16_t port) 88 | { 89 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 90 | throw std::runtime_error(strerror(errno)); 91 | } 92 | 93 | m_addr.sin_family = AF_INET; 94 | m_addr.sin_port = htons(port); 95 | m_addr.sin_addr.s_addr = htonl(INADDR_ANY); 96 | 97 | if (bind() == -1) { 98 | throw std::runtime_error(strerror(errno)); 99 | } 100 | } 101 | 102 | int bind() 103 | { 104 | return ::bind( 105 | m_fd, 106 | reinterpret_cast(&m_addr), 107 | sizeof(m_addr) 108 | ); 109 | } 110 | 111 | void listen() 112 | { 113 | if (::listen(m_fd, 0) == -1) { 114 | throw std::runtime_error(strerror(errno)); 115 | } 116 | 117 | while (true) { 118 | if (int c = ::accept(m_fd, nullptr, nullptr); c != -1) { 119 | std::thread t{log, c}; 120 | t.detach(); 121 | 122 | continue; 123 | } 124 | 125 | throw std::runtime_error(strerror(errno)); 126 | } 127 | } 128 | 129 | ~myserver() 130 | { 131 | close(m_fd); 132 | } 133 | }; 134 | 135 | int 136 | protected_main(int argc, char** argv) 137 | { 138 | (void) argc; 139 | (void) argv; 140 | 141 | myserver server{PORT}; 142 | server.listen(); 143 | } 144 | 145 | int 146 | main(int argc, char** argv) 147 | { 148 | try { 149 | return protected_main(argc, argv); 150 | } 151 | catch (const std::exception &e) { 152 | std::cerr << "Caught unhandled exception:\n"; 153 | std::cerr << " - what(): " << e.what() << '\n'; 154 | } 155 | catch (...) { 156 | std::cerr << "Caught unknown exception\n"; 157 | } 158 | 159 | return EXIT_FAILURE; 160 | } 161 | 162 | #endif 163 | 164 | #ifdef CLIENT 165 | 166 | #include 167 | #include 168 | 169 | #include 170 | #include 171 | #include 172 | 173 | #include 174 | #include 175 | 176 | #include 177 | #include 178 | 179 | #ifdef DEBUG_LEVEL 180 | constexpr auto g_debug_level = DEBUG_LEVEL; 181 | #else 182 | constexpr auto g_debug_level = 0; 183 | #endif 184 | 185 | #ifdef NDEBUG 186 | constexpr auto g_ndebug = true; 187 | #else 188 | constexpr auto g_ndebug = false; 189 | #endif 190 | 191 | class myclient 192 | { 193 | int m_fd{}; 194 | struct sockaddr_in m_addr{}; 195 | 196 | public: 197 | myclient(uint16_t port) 198 | { 199 | if (m_fd = ::socket(AF_INET, SOCK_STREAM, 0); m_fd == -1) { 200 | throw std::runtime_error(strerror(errno)); 201 | } 202 | 203 | m_addr.sin_family = AF_INET; 204 | m_addr.sin_port = htons(port); 205 | m_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 206 | 207 | if (connect() == -1) { 208 | throw std::runtime_error(strerror(errno)); 209 | } 210 | } 211 | 212 | int connect() 213 | { 214 | return ::connect( 215 | m_fd, 216 | reinterpret_cast(&m_addr), 217 | sizeof(m_addr) 218 | ); 219 | } 220 | 221 | ssize_t send(const std::string &buf) 222 | { 223 | return ::send( 224 | m_fd, 225 | buf.data(), 226 | buf.size(), 227 | 0 228 | ); 229 | } 230 | 231 | ~myclient() 232 | { 233 | close(m_fd); 234 | } 235 | }; 236 | 237 | myclient g_client{PORT}; 238 | std::fstream g_log{"client_log.txt", std::ios::out | std::ios::app}; 239 | 240 | template 241 | constexpr void log(void(*func)()) { 242 | if constexpr (!g_ndebug && (LEVEL <= g_debug_level)) { 243 | std::stringstream buf; 244 | 245 | auto g_buf = std::clog.rdbuf(); 246 | std::clog.rdbuf(buf.rdbuf()); 247 | 248 | func(); 249 | 250 | std::clog.rdbuf(g_buf); 251 | 252 | std::clog << "\033[1;32mDEBUG\033[0m: "; 253 | std::clog << buf.str(); 254 | 255 | g_log << "\033[1;32mDEBUG\033[0m: "; 256 | g_log << buf.str(); 257 | 258 | g_client.send("\033[1;32mDEBUG\033[0m: "); 259 | g_client.send(buf.str()); 260 | }; 261 | } 262 | 263 | int 264 | protected_main(int argc, char** argv) 265 | { 266 | (void) argc; 267 | (void) argv; 268 | 269 | log<0>([]{ 270 | std::clog << "Hello World\n"; 271 | }); 272 | 273 | std::clog << "Hello World\n"; 274 | 275 | return EXIT_SUCCESS; 276 | } 277 | 278 | int 279 | main(int argc, char** argv) 280 | { 281 | try { 282 | return protected_main(argc, argv); 283 | } 284 | catch (const std::exception &e) { 285 | std::cerr << "Caught unhandled exception:\n"; 286 | std::cerr << " - what(): " << e.what() << '\n'; 287 | } 288 | catch (...) { 289 | std::cerr << "Caught unknown exception\n"; 290 | } 291 | 292 | return EXIT_FAILURE; 293 | } 294 | 295 | #endif -------------------------------------------------------------------------------- /Chapter13/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2018 Rian Quinn 3 | # 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy 5 | # of this software and associated documentation files (the "Software"), to deal 6 | # in the Software without restriction, including without limitation the rights 7 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | # copies of the Software, and to permit persons to whom the Software is 9 | # furnished to do so, subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be included in all 12 | # copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | # ------------------------------------------------------------------------------ 23 | # Header 24 | # ------------------------------------------------------------------------------ 25 | 26 | cmake_minimum_required(VERSION 3.6) 27 | project(chapter13) 28 | 29 | include(ExternalProject) 30 | find_package(Git REQUIRED) 31 | 32 | set(CMAKE_CXX_STANDARD 17) 33 | 34 | # ------------------------------------------------------------------------------ 35 | # Guideline Support Library 36 | # ------------------------------------------------------------------------------ 37 | 38 | list(APPEND GSL_CMAKE_ARGS 39 | -DGSL_TEST=OFF 40 | -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR} 41 | ) 42 | 43 | ExternalProject_Add( 44 | gsl 45 | GIT_REPOSITORY https://github.com/Microsoft/GSL.git 46 | GIT_SHALLOW 1 47 | CMAKE_ARGS ${GSL_CMAKE_ARGS} 48 | PREFIX ${CMAKE_BINARY_DIR}/external/gsl/prefix 49 | TMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/tmp 50 | STAMP_DIR ${CMAKE_BINARY_DIR}/external/gsl/stamp 51 | DOWNLOAD_DIR ${CMAKE_BINARY_DIR}/external/gsl/download 52 | SOURCE_DIR ${CMAKE_BINARY_DIR}/external/gsl/src 53 | BINARY_DIR ${CMAKE_BINARY_DIR}/external/gsl/build 54 | UPDATE_DISCONNECTED 1 55 | ) 56 | 57 | # ------------------------------------------------------------------------------ 58 | # Executable 59 | # ------------------------------------------------------------------------------ 60 | 61 | include_directories(${CMAKE_BINARY_DIR}/include) 62 | 63 | add_executable(example1 example1.cpp) 64 | add_dependencies(example1 gsl) 65 | target_link_libraries(example1) 66 | 67 | # ------------------------------------------------------------------------------ 68 | # Snippets 69 | # ------------------------------------------------------------------------------ 70 | 71 | function(snippet number) 72 | add_executable(snippet${number} scratchpad.cpp) 73 | target_compile_definitions(snippet${number} PRIVATE SNIPPET${number}) 74 | target_link_libraries(snippet${number} pthread) 75 | endfunction(snippet) 76 | 77 | snippet(01) 78 | snippet(02) 79 | snippet(03) 80 | snippet(04) 81 | snippet(05) 82 | snippet(06) 83 | snippet(07) 84 | snippet(08) 85 | snippet(09) 86 | snippet(10) 87 | snippet(11) 88 | snippet(12) 89 | snippet(13) 90 | snippet(14) 91 | snippet(15) 92 | snippet(16) 93 | snippet(17) 94 | snippet(18) 95 | snippet(19) 96 | snippet(20) 97 | snippet(21) 98 | -------------------------------------------------------------------------------- /Chapter13/example1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (C) 2018 Rian Quinn 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in all 12 | // copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | // SOFTWARE. 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | jmp_buf jb; 28 | 29 | constexpr const auto bad = 0x10000000; 30 | constexpr const auto num_iterations = 100000; 31 | 32 | 33 | template 34 | auto benchmark(FUNC func) { 35 | auto stime = std::chrono::high_resolution_clock::now(); 36 | func(); 37 | auto etime = std::chrono::high_resolution_clock::now(); 38 | 39 | return (etime - stime).count(); 40 | } 41 | 42 | int myfunc1(int val) 43 | { 44 | if (val >= bad) { 45 | return -1; 46 | } 47 | 48 | if (val < 0x1000) { 49 | if (auto ret = myfunc1(val + 1); ret == -1) { 50 | return ret; 51 | } 52 | } 53 | 54 | return 0; 55 | } 56 | 57 | void myfunc2(int val) 58 | { 59 | if (val >= bad) { 60 | std::longjmp(jb, -1); 61 | } 62 | 63 | if (val < 0x1000) { 64 | myfunc2(val + 1); 65 | } 66 | } 67 | 68 | void myfunc3(int val) 69 | { 70 | if (val >= bad) { 71 | throw -1; 72 | } 73 | 74 | if (val < 0x1000) { 75 | myfunc3(val + 1); 76 | } 77 | } 78 | 79 | void test_func1() 80 | { 81 | if (auto ret = myfunc1(0); ret == 0) { 82 | std::cout << "myfunc1: success\n"; 83 | } 84 | else { 85 | std::cout << "myfunc1: failure\n"; 86 | } 87 | 88 | if (auto ret = myfunc1(bad); ret == 0) { 89 | std::cout << "myfunc1: success\n"; 90 | } 91 | else { 92 | std::cout << "myfunc1: failure\n"; 93 | } 94 | 95 | uint64_t total = 0; 96 | for (auto i = 0; i < num_iterations; i++) { 97 | total += benchmark([&] { 98 | myfunc1(0); 99 | }); 100 | } 101 | 102 | std::cout << "time1: " << total << '\n'; 103 | } 104 | 105 | void test_func2() 106 | { 107 | if (setjmp(jb) == -1) { 108 | std::cout << "myfunc2: failure\n"; 109 | 110 | uint64_t total = 0; 111 | for (auto i = 0; i < num_iterations; i++) { 112 | total += benchmark([&] { 113 | myfunc2(0); 114 | }); 115 | } 116 | 117 | std::cout << "time2: " << total << '\n'; 118 | return; 119 | } 120 | 121 | myfunc2(0); 122 | std::cout << "myfunc2: success\n"; 123 | 124 | myfunc2(bad); 125 | std::cout << "myfunc2: success\n"; 126 | } 127 | 128 | void test_func3() 129 | { 130 | try { 131 | myfunc3(0); 132 | std::cout << "myfunc3: success\n"; 133 | 134 | myfunc3(bad); 135 | std::cout << "myfunc3: success\n"; 136 | } 137 | catch(...) { 138 | std::cout << "myfunc3: failure\n"; 139 | } 140 | 141 | uint64_t total = 0; 142 | for (auto i = 0; i < num_iterations; i++) { 143 | total += benchmark([&] { 144 | myfunc3(0); 145 | }); 146 | } 147 | 148 | std::cout << "time3: " << total << '\n'; 149 | } 150 | 151 | int 152 | protected_main(int argc, char** argv) 153 | { 154 | (void) argc; 155 | (void) argv; 156 | 157 | test_func1(); 158 | test_func2(); 159 | test_func3(); 160 | 161 | return EXIT_SUCCESS; 162 | } 163 | 164 | int 165 | main(int argc, char** argv) 166 | { 167 | try { 168 | return protected_main(argc, argv); 169 | } 170 | catch (const std::exception &e) { 171 | std::cerr << "Caught unhandled exception:\n"; 172 | std::cerr << " - what(): " << e.what() << '\n'; 173 | } 174 | catch (...) { 175 | std::cerr << "Caught unknown exception\n"; 176 | } 177 | 178 | return EXIT_FAILURE; 179 | } 180 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Hands-On System Programming with C++ 5 | 6 | Hands-On System Programming with C++ 7 | 8 | This is the code repository for [Hands-On System Programming with C++](https://www.packtpub.com/application-development/hands-system-programming-c?utm_source=github&utm_medium=repository&utm_campaign=9781789137880 ), published by Packt. 9 | 10 | **Build performant and concurrent Unix and Linux systems with C++17 ** 11 | 12 | ## What is this book about? 13 | C++ is a general-purpose programming language with a bias toward system programming as it provides ready access to hardware-level resources, efficient compilation, and a versatile approach to higher-level abstractions. 14 | 15 | This book covers the following exciting features: 16 | * Understand the benefits of using C++ for system programming 17 | * Program Linux/Unix systems using C++ 18 | * Discover the advantages of Resource Acquisition Is Initialization (RAII) 19 | * Program both console and file input and output 20 | * Uncover the POSIX socket APIs and understand how to program them 21 | * Explore advanced system programming topics, such as C++ allocators 22 | * Use POSIX and C++ threads to program concurrent systems 23 | * Grasp how C++ can be used to create performant system applications 24 | 25 | If you feel this book is for you, get your [copy](https://www.amazon.com/dp/1789137888) today! 26 | 27 | https://www.packtpub.com/ 29 | 30 | ## Instructions and Navigations 31 | All of the code is organized into folders. For example, Chapter02. 32 | 33 | The code will look like the following: 34 | ``` 35 | int array[10]; 36 | 37 | auto r1 = array + 1; 38 | auto r2 = *(array + 1); 39 | auto r3 = array[1]; 40 | ``` 41 | 42 | **Following is what you need for this book:** 43 | If you are a fresh developer with intermediate knowledge of C++ but little or no knowledge of Unix and Linux system programming, this book will help you learn system programming with C++ in a practical way. 44 | 45 | With the following software and hardware list you can run all code files present in the book (Chapter 1-13). 46 | ### Software and Hardware List 47 | | Chapter | Software required | OS required | 48 | | -------- | ------------------------------------ | ----------------------------------- | 49 | | 1-13 | GCC 7+ | Ubuntu 17.10+ | 50 | | 1-13 | CMake 3.6+ | Ubuntu 17.10+ | 51 | 52 | ### Related products 53 | * C++ Data Structures and Algorithms [[Packt]](https://www.packtpub.com/application-development/c-data-structures-and-algorithms?utm_source=github&utm_medium=repository&utm_campaign=9781788835213 ) [[Amazon]](https://www.amazon.com/dp/1788835212) 54 | 55 | * C++ Reactive Programming [[Packt]](https://www.packtpub.com/application-development/c-reactive-programming?utm_source=github&utm_medium=repository&utm_campaign=9781788629775 ) [[Amazon]](https://www.amazon.com/dp/1788629779) 56 | 57 | ## Get to Know the Author 58 | **Dr. Rian Quinn** 59 | is a Chief Technology Officer (CTO) in the Advanced Technologies Business Unit at Assured Information Security, Inc. focused on trusted computing, hypervisor related technologies, machine learning/artificial intelligence, and cyber security for more than 10 years and has 9 years of technical management and business development experience. He holds a Ph.D. in Computer Engineering, specializations in information assurance and computer architectures, from Binghamton University. He is the co-founder and lead developer of the Bareflank Hypervisor, and is an active member of several open source projects, including Microsoft's Guideline Support Library (GSL) and OpenXT. 60 | 61 | ### Suggestions and Feedback 62 | [Click here](https://docs.google.com/forms/d/e/1FAIpQLSdy7dATC6QmEL81FIUuymZ0Wy9vH1jHkvpY57OiMeKGqib_Ow/viewform) if you have any feedback or suggestions. 63 | 64 | 65 | ### Download a free PDF 66 | 67 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.
68 |

https://packt.link/free-ebook/9781789137880

--------------------------------------------------------------------------------