├── README ├── cpp_thread_00.cpp ├── cpp_thread_01.cpp ├── cpp_thread_02.cpp ├── image_processing ├── ppm.cpp ├── ppm.h └── ppm_05.cpp ├── part_2 ├── cpp11_threads_00.cpp ├── cpp11_threads_01.cpp ├── cpp11_threads_02.cpp └── cpp11_threads_03.cpp ├── part_3 ├── threads_00.cpp └── threads_01.cpp ├── posix_thread_00.cpp ├── posix_thread_01.cpp └── posix_thread_02.cpp /README: -------------------------------------------------------------------------------- 1 | Here you could find the code for "C++11 thread tutorial", for more informations visit the project webpage: 2 | 3 | http://solarianprogrammer.com/2011/12/16/cpp-11-thread-tutorial/ 4 | 5 | or: 6 | 7 | http://solarianprogrammer.com/2012/02/27/cpp-11-thread-tutorial-part-2/ 8 | 9 | for the second part of this tutorial. 10 | 11 | In order to use the image_processing code you will need a picture in ppm format, you can easily find examples 12 | on the Internet, or you could use Gimp to save your own picture in ppm format. 13 | 14 | You could use this program under the terms of GPL v3, for more details see: 15 | 16 | http://www.gnu.org/copyleft/gpl.html 17 | 18 | Copyright 2011 Sol from www.solarianprogrammer.com 19 | -------------------------------------------------------------------------------- /cpp_thread_00.cpp: -------------------------------------------------------------------------------- 1 | //Create a C++11 thread from the main program 2 | 3 | #include 4 | #include 5 | 6 | //This function will be called from a thread 7 | 8 | void call_from_thread() { 9 | std::cout << "Hello, World!" << std::endl; 10 | } 11 | 12 | int main() { 13 | //Launch a thread 14 | std::thread t1(call_from_thread); 15 | 16 | //Join the thread with the main thread 17 | t1.join(); 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /cpp_thread_01.cpp: -------------------------------------------------------------------------------- 1 | //Create a group of C++11 threads from the main program 2 | 3 | #include 4 | #include 5 | 6 | static const int num_threads = 10; 7 | 8 | //This function will be called from a thread 9 | 10 | void call_from_thread() { 11 | std::cout << "Launched by thread\n"; 12 | } 13 | 14 | int main() { 15 | std::thread t[num_threads]; 16 | 17 | //Launch a group of threads 18 | for (int i = 0; i < num_threads; ++i) { 19 | t[i] = std::thread(call_from_thread); 20 | } 21 | 22 | std::cout << "Launched from the main\n"; 23 | 24 | //Join the threads with the main thread 25 | for (int i = 0; i < num_threads; ++i) { 26 | t[i].join(); 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /cpp_thread_02.cpp: -------------------------------------------------------------------------------- 1 | //Create a group of C++11 threads from the main program 2 | 3 | #include 4 | #include 5 | 6 | static const int num_threads = 10; 7 | 8 | //This function will be called from a thread 9 | 10 | void call_from_thread(int tid) { 11 | std::cout << "Launched by thread " << tid << std::endl; 12 | } 13 | 14 | int main() { 15 | std::thread t[num_threads]; 16 | 17 | //Launch a group of threads 18 | for (int i = 0; i < num_threads; ++i) { 19 | t[i] = std::thread(call_from_thread, i); 20 | } 21 | 22 | std::cout << "Launched from the main\n"; 23 | 24 | //Join the threads with the main thread 25 | for (int i = 0; i < num_threads; ++i) { 26 | t[i].join(); 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /image_processing/ppm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ppm.h" 9 | 10 | //init with default values 11 | 12 | void ppm::init() { 13 | width = 0; 14 | height = 0; 15 | max_col_val = 255; 16 | } 17 | 18 | //create a PPM object 19 | 20 | ppm::ppm() { 21 | init(); 22 | } 23 | 24 | //create a PPM object and fill it with data stored in fname 25 | 26 | ppm::ppm(const std::string &fname) { 27 | init(); 28 | read(fname); 29 | } 30 | 31 | //create an "epmty" PPM image with a given width and height;the R,G,B arrays are filled with zeros 32 | 33 | ppm::ppm(const unsigned int _width, const unsigned int _height) { 34 | init(); 35 | width = _width; 36 | height = _height; 37 | nr_lines = height; 38 | nr_columns = width; 39 | size = width*height; 40 | 41 | r.resize(size); 42 | g.resize(size); 43 | b.resize(size); 44 | 45 | for (unsigned int i = 0; i < size; ++i) { 46 | r[i] = 0; 47 | g[i] = 0; 48 | b[i] = 0; 49 | } 50 | } 51 | 52 | //read the PPM image from fname 53 | 54 | void ppm::read(const std::string &fname) { 55 | std::ifstream inp(fname.c_str(), std::ios::in | std::ios::binary); 56 | if (inp.is_open()) { 57 | std::string line; 58 | std::getline(inp, line); 59 | if (line != "P6") { 60 | std::cout << "Error. Unrecognized file format." << std::endl; 61 | return; 62 | } 63 | std::getline(inp, line); 64 | while (line[0] == '#') { 65 | std::getline(inp, line); 66 | } 67 | std::stringstream dimensions(line); 68 | 69 | try { 70 | dimensions >> width; 71 | dimensions >> height; 72 | nr_lines = height; 73 | nr_columns = width; 74 | } catch (std::exception &e) { 75 | std::cout << "Header file format error. " << e.what() << std::endl; 76 | return; 77 | } 78 | 79 | std::getline(inp, line); 80 | std::stringstream max_val(line); 81 | try { 82 | max_val >> max_col_val; 83 | } catch (std::exception &e) { 84 | std::cout << "Header file format error. " << e.what() << std::endl; 85 | return; 86 | } 87 | 88 | size = width*height; 89 | 90 | r.resize(size); 91 | g.resize(size); 92 | b.resize(size); 93 | 94 | char aux; 95 | for (unsigned int i = 0; i < size; ++i) { 96 | inp.read(&aux, 1); 97 | r[i] = (unsigned char) aux; 98 | inp.read(&aux, 1); 99 | g[i] = (unsigned char) aux; 100 | inp.read(&aux, 1); 101 | b[i] = (unsigned char) aux; 102 | } 103 | } else { 104 | std::cout << "Error. Unable to open " << fname << std::endl; 105 | } 106 | inp.close(); 107 | } 108 | 109 | //write the PPM image in fname 110 | 111 | void ppm::write(const std::string &fname) { 112 | std::ofstream inp(fname.c_str(), std::ios::out | std::ios::binary); 113 | if (inp.is_open()) { 114 | 115 | inp << "P6\n"; 116 | inp << width; 117 | inp << " "; 118 | inp << height << "\n"; 119 | inp << max_col_val << "\n"; 120 | 121 | char aux; 122 | for (unsigned int i = 0; i < size; ++i) { 123 | aux = (char) r[i]; 124 | inp.write(&aux, 1); 125 | aux = (char) g[i]; 126 | inp.write(&aux, 1); 127 | aux = (char) b[i]; 128 | inp.write(&aux, 1); 129 | } 130 | } else { 131 | std::cout << "Error. Unable to open " << fname << std::endl; 132 | } 133 | inp.close(); 134 | } 135 | -------------------------------------------------------------------------------- /image_processing/ppm.h: -------------------------------------------------------------------------------- 1 | //Process a binary PPM file 2 | 3 | class ppm { 4 | void init(); 5 | //info about the PPM file (height and width) 6 | unsigned int nr_lines; 7 | unsigned int nr_columns; 8 | 9 | public: 10 | //arrays for storing the R,G,B values 11 | std::vector r; 12 | std::vector g; 13 | std::vector b; 14 | // 15 | unsigned int height; 16 | unsigned int width; 17 | unsigned int max_col_val; 18 | //total number of elements (pixels) 19 | unsigned int size; 20 | 21 | ppm(); 22 | //create a PPM object and fill it with data stored in fname 23 | ppm(const std::string &fname); 24 | //create an "epmty" PPM image with a given width and height;the R,G,B arrays are filled with zeros 25 | ppm(const unsigned int _width, const unsigned int _height); 26 | //read the PPM image from fname 27 | void read(const std::string &fname); 28 | //write the PPM image in fname 29 | void write(const std::string &fname); 30 | }; 31 | -------------------------------------------------------------------------------- /image_processing/ppm_05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "ppm.h" 7 | 8 | //Split "mem" into "parts", e.g. if mem = 10 and parts = 4 you will have: 0,2,4,6,10 9 | //if possible the function will split mem into equal chuncks, if not 10 | //the last chunck will be slightly larger 11 | 12 | std::vector bounds(int parts, int mem) { 13 | std::vectorbnd; 14 | int delta = mem / parts; 15 | int reminder = mem % parts; 16 | int N1 = 0, N2 = 0; 17 | bnd.push_back(N1); 18 | for (int i = 0; i < parts; ++i) { 19 | N2 = N1 + delta; 20 | if (i == parts - 1) 21 | N2 += reminder; 22 | bnd.push_back(N2); 23 | N1 = N2; 24 | } 25 | return bnd; 26 | } 27 | 28 | //Test if a given position (ii,jj) is "inside" the limits 0..nr_lines and 0..nr_columns 29 | 30 | bool border(int ii, int jj, int nr_lines, int nr_columns) { 31 | if (ii >= 0 && ii < nr_lines && jj >= 0 && jj < nr_columns) 32 | return true; 33 | else 34 | return false; 35 | } 36 | 37 | //Blur the pixel at (i,j) using information from the neighbour pixels 38 | 39 | void process(ppm &image, ppm &image2, int i, int j) { 40 | int ii, jj, nr_lines, nr_columns, indx; 41 | unsigned int r, g, b; 42 | float r_sum, g_sum, b_sum; 43 | //Filter used for bluring an image 44 | float filter[] = { 45 | 0.10179640718562874, 0.11377245508982035, 0.10179640718562874, 46 | 0.11377245508982035, 0.1377245508982036, 0.11377245508982035, 47 | 0.10179640718562874, 0.11377245508982035, 0.10179640718562874 48 | }; 49 | 50 | nr_lines = image.height; 51 | nr_columns = image.width; 52 | 53 | //Apply the filter: 54 | r_sum = 0; 55 | g_sum = 0; 56 | b_sum = 0; 57 | 58 | //check North-West 59 | ii = i - 1; 60 | jj = j - 1; 61 | if (border(ii, jj, nr_lines, nr_columns)) { 62 | indx = ii * image.width + jj; 63 | 64 | r = (unsigned int) image.r[indx]; 65 | g = (unsigned int) image.g[indx]; 66 | b = (unsigned int) image.b[indx]; 67 | 68 | r_sum += r * filter[0]; 69 | g_sum += g * filter[0]; 70 | b_sum += b * filter[0]; 71 | } 72 | 73 | //check North 74 | ii = i - 1; 75 | jj = j; 76 | if (border(ii, jj, nr_lines, nr_columns)) { 77 | indx = ii * image.width + jj; 78 | 79 | r = (unsigned int) image.r[indx]; 80 | g = (unsigned int) image.g[indx]; 81 | b = (unsigned int) image.b[indx]; 82 | 83 | r_sum += r * filter[1]; 84 | g_sum += g * filter[1]; 85 | b_sum += b * filter[1]; 86 | } 87 | 88 | //check North-East 89 | ii = i - 1; 90 | jj = j + 1; 91 | if (border(ii, jj, nr_lines, nr_columns)) { 92 | indx = ii * image.width + jj; 93 | 94 | r = (unsigned int) image.r[indx]; 95 | g = (unsigned int) image.g[indx]; 96 | b = (unsigned int) image.b[indx]; 97 | 98 | r_sum += r * filter[2]; 99 | g_sum += g * filter[2]; 100 | b_sum += b * filter[2]; 101 | } 102 | 103 | //check West 104 | ii = i; 105 | jj = j - 1; 106 | if (border(ii, jj, nr_lines, nr_columns)) { 107 | indx = ii * image.width + jj; 108 | 109 | r = (unsigned int) image.r[indx]; 110 | g = (unsigned int) image.g[indx]; 111 | b = (unsigned int) image.b[indx]; 112 | 113 | r_sum += r * filter[3]; 114 | g_sum += g * filter[3]; 115 | b_sum += b * filter[3]; 116 | } 117 | 118 | //center 119 | ii = i; 120 | jj = j; 121 | indx = ii * image.width + jj; 122 | 123 | r = (unsigned int) image.r[indx]; 124 | g = (unsigned int) image.g[indx]; 125 | b = (unsigned int) image.b[indx]; 126 | 127 | r_sum += r * filter[4]; 128 | g_sum += g * filter[4]; 129 | b_sum += b * filter[4]; 130 | 131 | 132 | //check East 133 | ii = i; 134 | jj = j + 1; 135 | if (border(ii, jj, nr_lines, nr_columns)) { 136 | indx = ii * image.width + jj; 137 | 138 | r = (unsigned int) image.r[indx]; 139 | g = (unsigned int) image.g[indx]; 140 | b = (unsigned int) image.b[indx]; 141 | 142 | r_sum += r * filter[5]; 143 | g_sum += g * filter[5]; 144 | b_sum += b * filter[5]; 145 | } 146 | //check South-West 147 | ii = i + 1; 148 | jj = j - 1; 149 | if (border(ii, jj, nr_lines, nr_columns)) { 150 | indx = ii * image.width + jj; 151 | 152 | r = (unsigned int) image.r[indx]; 153 | g = (unsigned int) image.g[indx]; 154 | b = (unsigned int) image.b[indx]; 155 | 156 | r_sum += r * filter[6]; 157 | g_sum += g * filter[6]; 158 | b_sum += b * filter[6]; 159 | } 160 | //check South 161 | ii = i + 1; 162 | jj = j; 163 | if (border(ii, jj, nr_lines, nr_columns)) { 164 | indx = ii * image.width + jj; 165 | 166 | r = (unsigned int) image.r[indx]; 167 | g = (unsigned int) image.g[indx]; 168 | b = (unsigned int) image.b[indx]; 169 | 170 | r_sum += r * filter[7]; 171 | g_sum += g * filter[7]; 172 | b_sum += b * filter[7]; 173 | } 174 | //check South-East 175 | ii = i + 1; 176 | jj = j + 1; 177 | if (border(ii, jj, nr_lines, nr_columns)) { 178 | indx = ii * image.width + jj; 179 | 180 | r = (unsigned int) image.r[indx]; 181 | g = (unsigned int) image.g[indx]; 182 | b = (unsigned int) image.b[indx]; 183 | 184 | r_sum += r * filter[8]; 185 | g_sum += g * filter[8]; 186 | b_sum += b * filter[8]; 187 | } 188 | 189 | //Save the modifed pixel value in image2 190 | indx = i * image.width + j; 191 | image2.r[indx] = (unsigned char) r_sum; 192 | image2.g[indx] = (unsigned char) g_sum; 193 | image2.b[indx] = (unsigned char) b_sum; 194 | } 195 | 196 | //Blur a chunck of an image 197 | 198 | void tst(ppm &image, ppm &image2, int left, int right) { 199 | for (int i = left; i < right; ++i) { 200 | int ii = i / image.width; 201 | int jj = i - ii * image.width; 202 | process(image, image2, ii, jj); 203 | } 204 | } 205 | 206 | int main() { 207 | std::string fname = std::string("your_file_name.ppm"); 208 | 209 | ppm image(fname); 210 | ppm image2(image.width, image.height); 211 | 212 | //Number of threads to use (the image will be divided between threads) 213 | int parts = 4; 214 | 215 | std::vectorbnd = bounds(parts, image.size); 216 | 217 | //std::vector tt(parts-1); 218 | std::vector tt; 219 | 220 | time_t start, end; 221 | time(&start); 222 | //Lauch parts-1 threads 223 | for (int i = 0; i < parts - 1; ++i) { 224 | tt.push_back(std::thread(tst, std::ref(image), std::ref(image2), bnd[i], bnd[i + 1])); 225 | //tt[i] = std::thread(tst, std::ref(image), std::ref(image2), bnd[i], bnd[i + 1]); 226 | } 227 | 228 | //Use the main thread to do part of the work !!! 229 | for (int i = parts - 1; i < parts; ++i) { 230 | tst(image, image2, bnd[i], bnd[i + 1]); 231 | } 232 | 233 | //Join parts-1 threads 234 | for(auto &e : tt){ 235 | e.join(); 236 | } 237 | //for(int i = 0; i < parts - 1; ++i){ 238 | // tt[i].join(); 239 | //} 240 | 241 | time(&end); 242 | std::cout << difftime(end, start) << " seconds" << std::endl; 243 | 244 | //Save the result 245 | image2.write("test.ppm"); 246 | 247 | return 0; 248 | } 249 | -------------------------------------------------------------------------------- /part_2/cpp11_threads_00.cpp: -------------------------------------------------------------------------------- 1 | //Create a group of C++11 threads from the main program 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | //This function will be called from a thread 8 | 9 | void func(int tid) { 10 | std::cout << "Launched by thread " << tid << std::endl; 11 | } 12 | 13 | int main() { 14 | std::vector th; 15 | 16 | int nr_threads = 10; 17 | 18 | //Launch a group of threads 19 | for (int i = 0; i < nr_threads; ++i) { 20 | th.push_back(std::thread(func,i)); 21 | } 22 | 23 | //Join the threads with the main thread 24 | for(auto &t : th){ 25 | t.join(); 26 | } 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /part_2/cpp11_threads_01.cpp: -------------------------------------------------------------------------------- 1 | // Naive paralle dot product implementation, example of race condition 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | //Split "mem" into "parts", e.g. if mem = 10 and parts = 4 you will have: 0,2,4,6,10 8 | //if possible the function will split mem into equal chuncks, if not 9 | //the last chunck will be slightly larger 10 | 11 | std::vector bounds(int parts, int mem) { 12 | std::vectorbnd; 13 | int delta = mem / parts; 14 | int reminder = mem % parts; 15 | int N1 = 0, N2 = 0; 16 | bnd.push_back(N1); 17 | for (int i = 0; i < parts; ++i) { 18 | N2 = N1 + delta; 19 | if (i == parts - 1) 20 | N2 += reminder; 21 | bnd.push_back(N2); 22 | N1 = N2; 23 | } 24 | return bnd; 25 | } 26 | 27 | void dot_product(const std::vector &v1, const std::vector &v2, int &result, int L, int R){ 28 | for(int i = L; i < R; ++i){ 29 | result += v1[i] * v2[i]; 30 | } 31 | } 32 | 33 | int main(){ 34 | int nr_elements = 100000; 35 | int nr_threads = 2; 36 | int result = 0; 37 | std::vector threads; 38 | 39 | //Fill two vectors with some values 40 | std::vector v1(nr_elements,1), v2(nr_elements,2); 41 | 42 | //Split nr_elements into nr_threads parts 43 | std::vector limits = bounds(nr_threads, nr_elements); 44 | 45 | //Launch nr_threads threads: 46 | for (int i = 0; i < nr_threads; ++i) { 47 | threads.push_back(std::thread(dot_product, std::ref(v1), std::ref(v2), std::ref(result), limits[i], limits[i+1])); 48 | } 49 | 50 | 51 | //Join the threads with the main thread 52 | for(auto &t : threads){ 53 | t.join(); 54 | } 55 | 56 | //Print the result 57 | std::cout< 4 | #include 5 | #include 6 | #include 7 | 8 | static std::mutex barrier; 9 | 10 | //Split "mem" into "parts", e.g. if mem = 10 and parts = 4 you will have: 0,2,4,6,10 11 | //if possible the function will split mem into equal chuncks, if not 12 | //the last chunck will be slightly larger 13 | 14 | std::vector bounds(int parts, int mem) { 15 | std::vectorbnd; 16 | int delta = mem / parts; 17 | int reminder = mem % parts; 18 | int N1 = 0, N2 = 0; 19 | bnd.push_back(N1); 20 | for (int i = 0; i < parts; ++i) { 21 | N2 = N1 + delta; 22 | if (i == parts - 1) 23 | N2 += reminder; 24 | bnd.push_back(N2); 25 | N1 = N2; 26 | } 27 | return bnd; 28 | } 29 | 30 | void dot_product(const std::vector &v1, const std::vector &v2, int &result, int L, int R){ 31 | int partial_sum = 0; 32 | for(int i = L; i < R; ++i){ 33 | partial_sum += v1[i] * v2[i]; 34 | } 35 | std::lock_guard block_threads_until_finish_this_job(barrier); 36 | result += partial_sum; 37 | } 38 | 39 | int main(){ 40 | int nr_elements = 100000; 41 | int nr_threads = 2; 42 | int result = 0; 43 | std::vector threads; 44 | 45 | //Fill two vectors with some values 46 | std::vector v1(nr_elements,1), v2(nr_elements,2); 47 | 48 | //Split nr_elements into nr_threads parts 49 | std::vector limits = bounds(nr_threads, nr_elements); 50 | 51 | //Launch nr_threads threads: 52 | for (int i = 0; i < nr_threads; ++i) { 53 | threads.push_back(std::thread(dot_product, std::ref(v1), std::ref(v2), std::ref(result), limits[i], limits[i+1])); 54 | } 55 | 56 | 57 | //Join the threads with the main thread 58 | for(auto &t : threads){ 59 | t.join(); 60 | } 61 | 62 | //Print the result 63 | std::cout< 4 | #include 5 | #include 6 | #include 7 | 8 | //Split "mem" into "parts", e.g. if mem = 10 and parts = 4 you will have: 0,2,4,6,10 9 | //if possible the function will split mem into equal chuncks, if not 10 | //the last chunck will be slightly larger 11 | 12 | std::vector bounds(int parts, int mem) { 13 | std::vectorbnd; 14 | int delta = mem / parts; 15 | int reminder = mem % parts; 16 | int N1 = 0, N2 = 0; 17 | bnd.push_back(N1); 18 | for (int i = 0; i < parts; ++i) { 19 | N2 = N1 + delta; 20 | if (i == parts - 1) 21 | N2 += reminder; 22 | bnd.push_back(N2); 23 | N1 = N2; 24 | } 25 | return bnd; 26 | } 27 | 28 | void dot_product(const std::vector &v1, const std::vector &v2, std::atomic &result, int L, int R){ 29 | int partial_sum = 0; 30 | for(int i = L; i < R; ++i){ 31 | partial_sum += v1[i] * v2[i]; 32 | } 33 | result += partial_sum; 34 | } 35 | 36 | int main(){ 37 | int nr_elements = 100000; 38 | int nr_threads = 2; 39 | std::atomic result(0); 40 | std::vector threads; 41 | 42 | //Fill two vectors with some values 43 | std::vector v1(nr_elements,1), v2(nr_elements,2); 44 | 45 | //Split nr_elements into nr_threads parts 46 | std::vector limits = bounds(nr_threads, nr_elements); 47 | 48 | //Launch nr_threads threads: 49 | for (int i = 0; i < nr_threads; ++i) { 50 | threads.push_back(std::thread(dot_product, std::ref(v1), std::ref(v2), std::ref(result), limits[i], limits[i+1])); 51 | } 52 | 53 | 54 | //Join the threads with the main thread 55 | for(auto &t : threads){ 56 | t.join(); 57 | } 58 | 59 | //Print the result 60 | std::cout< 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | class SaylHello{ 10 | public: 11 | 12 | //This function will be called from a thread 13 | void func(const string &name) { 14 | cout <<"Hello " << name << endl; 15 | }; 16 | }; 17 | 18 | int main(int argc, char* argv[]) 19 | { 20 | SaylHello x; 21 | 22 | //Use a member function in a thread 23 | thread t(&SaylHello::func, &x, "Tom"); 24 | 25 | //Join the thread with the main thread 26 | t.join(); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /part_3/threads_01.cpp: -------------------------------------------------------------------------------- 1 | //Using lambda in a thread 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | //Use of an anonymous function (lambda) in a thread 12 | thread t( [] (string name) { 13 | cout << "Hello " << name << endl; 14 | }, "Tom"); 15 | 16 | //Join the thread with the main thread 17 | t.join(); 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /posix_thread_00.cpp: -------------------------------------------------------------------------------- 1 | //Create a Posix thread from the main program 2 | 3 | #include 4 | #include 5 | 6 | //This function will be called from a thread 7 | 8 | void *call_from_thread(void *) { 9 | std::cout << "Launched by thread" << std::endl; 10 | return NULL; 11 | } 12 | 13 | int main() { 14 | pthread_t t; 15 | 16 | //Launch a thread 17 | pthread_create(&t, NULL, call_from_thread, NULL); 18 | 19 | //Join the thread with the main thread 20 | pthread_join(t, NULL); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /posix_thread_01.cpp: -------------------------------------------------------------------------------- 1 | //Create a group of Posix threads from the main program 2 | 3 | #include 4 | #include 5 | 6 | static const int num_threads = 10; 7 | 8 | //This function will be called from a thread 9 | 10 | void *call_from_thread(void *) { 11 | std::cout << "Launched by thread\n"; 12 | return NULL; 13 | } 14 | 15 | int main() { 16 | pthread_t t[num_threads]; 17 | 18 | //Launch a group of threads 19 | for (int i = 0; i < num_threads; ++i) { 20 | pthread_create(&t[i], NULL, call_from_thread, NULL); 21 | } 22 | 23 | std::cout << "Launched from the main\n"; 24 | 25 | //Join the threads with the main thread 26 | for (int i = 0; i < num_threads; ++i) { 27 | pthread_join(t[i], NULL); 28 | } 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /posix_thread_02.cpp: -------------------------------------------------------------------------------- 1 | //Create a group of Posix threads from the main program 2 | 3 | #include 4 | #include 5 | 6 | static const int num_threads = 10; 7 | 8 | typedef struct { 9 | int thread_id; 10 | } thread_data; 11 | 12 | //This function will be called from a thread 13 | 14 | void *call_from_thread(void *args) { 15 | thread_data *my_data = (thread_data *) args; 16 | std::cout << "Launched by thread " << my_data->thread_id << std::endl; 17 | return NULL; 18 | } 19 | 20 | int main() { 21 | pthread_t t[num_threads]; 22 | thread_data td[num_threads]; 23 | 24 | //Launch a group of threads 25 | for (int i = 0; i < num_threads; ++i) { 26 | td[i].thread_id = i; 27 | pthread_create(&t[i], NULL, call_from_thread, (void *) &td[i]); 28 | } 29 | 30 | std::cout << "Launched from the main\n"; 31 | 32 | //Join the threads with the main thread 33 | for (int i = 0; i < num_threads; ++i) { 34 | pthread_join(t[i], NULL); 35 | } 36 | 37 | return 0; 38 | } 39 | --------------------------------------------------------------------------------