/* Credits for drawing the Mandelbrot set in C++ go to * Farouk Ounane (https://github.com/ChinksofLight/mandelbrot_cpp) */ #include <iostream> #include <fstream> // write to file #include <complex> // complex numbers #include <cmath> // pow #include "workerpool.hpp" constexpr int width = 1200; constexpr int height = 1200; constexpr int max_iter = 1000; constexpr int col_depth = 255; int main() { // initiate a worker pool WorkerPool wp(8); // Use 8 threads // make an array of values int vals[width][height]; std::cout << "passing tasks to worker pool..." << std::endl; for ( int i = 0; i < width; ++i ) { for ( int j = 0; j < height; ++j ) { /* use a closure to define the WorkerPool::Task object * the vals array is captured by reference. * NB: we have to capture i and j by value! */ wp.push_back([=,&vals](){ double x = double(i)/width-1.5; double y = double(j)/height-0.5; std::complex<double> point(x, y); // determine if point is in the Mandelbrot set... std::complex<double> z(0, 0); int nb_iter = 0; while ( std::abs(z) < 2 && nb_iter <= max_iter) { z = z * z + point; nb_iter++; } if ( nb_iter < max_iter ) { // determine color gradient double frac = double(nb_iter) / max_iter; vals[i][j] = int(col_depth * pow(frac, 0.25)); } else { vals[i][j] = 0; } }); } } std::cout << "waiting for workers..." << std::endl; /* before we sync the worker pool, the values in vals * are invalid. accessing them would lead to data races. */ wp.sync(); /* now all values have been computed and stored in vals. * The WorkerPool is still waiting for new tasks. * For example, we could use it to write the data * to a file in the background. */ wp.push_back([&](){ std::ofstream image_file("mandelbrot.ppm"); if ( !image_file.is_open() ) { std::cerr << "could not open the image file" << std::endl; return; } // else image_file << "P3\n" << width << " " << height << " " << col_depth << "\n"; for ( int j = 0; j < height; j++ ) { for ( int i = 0; i < width; i++ ) { int val = vals[i][j]; image_file << 0 << " " << val << " " << val << "\n"; } } image_file.close(); }); std::cout << "writing results to file..." << std::endl; // before we return, we have to wait for the writing task to be completed wp.sync(); return 0; }