diff --git a/concurrent_example/Makefile b/concurrent_example/Makefile new file mode 100644 index 0000000..c8288ef --- /dev/null +++ b/concurrent_example/Makefile @@ -0,0 +1,12 @@ +CC = g++ +#--------------------------------------------------------- +CPPFLAGS=-I../include +LDFLAGS=-pthread +#--------------------------------------------------------- +MAIN="concurrent_example" +#--------------------------------------------------------- +all: ${MAIN} + +${MAIN}: + ${CC} ${MAIN}.cpp -o ${MAIN} ${CPPFLAGS} ${LDFLAGS} + diff --git a/concurrent_example/concurrent_example.cpp b/concurrent_example/concurrent_example.cpp new file mode 100644 index 0000000..47fb2bc --- /dev/null +++ b/concurrent_example/concurrent_example.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include "progresscpp/ProgressBar.hpp" + +/* + * Function which is thrown as thread + */ +void workerThread(int total, progresscpp::ProgressBar& progressBar) { + for (int i = 0; i < total; i++) { + ++progressBar; // record the tick + + usleep(200); // simulate work + + // display the bar only at certain steps + if (i % 10 == 0) + progressBar.display(); + } +} + +/* Example usage of ProgressBar by multiple threads */ +int main() { + const int partial = 1000; + + /* + * Define a progress bar that has a total of 10000, + * a width of 70, shows `#` to indicate completion + * and a dash '-' for incomplete + */ + progresscpp::ProgressBar progressBar(10 * partial, 70, '#', '-'); + + /* + * Throw ten threads which access the same ProgressBar + * instance concurrently + */ + std::thread workers[10]; + for (int i = 0; i < 10; i++) { + workers[i] = std::thread(workerThread, partial, std::ref(progressBar)); + } + + /* + * Wait for threads to finish the work + */ + for (int i = 0; i < 10; i++) { + workers[i].join(); + } + + // tell the bar to finish + progressBar.done(); + + std::cout << "Done!" << std::endl; + return 0; +} diff --git a/include/progresscpp/ProgressBar.hpp b/include/progresscpp/ProgressBar.hpp index e4c4cf3..6160e47 100644 --- a/include/progresscpp/ProgressBar.hpp +++ b/include/progresscpp/ProgressBar.hpp @@ -2,11 +2,13 @@ #include #include +#include namespace progresscpp { class ProgressBar { private: unsigned int ticks = 0; + mutable std::mutex mtx; const unsigned int total_ticks; const unsigned int bar_width; @@ -20,7 +22,10 @@ class ProgressBar { ProgressBar(unsigned int total, unsigned int width) : total_ticks{total}, bar_width{width} {} - unsigned int operator++() { return ++ticks; } + unsigned int operator++() { + std::unique_lock lck (mtx); + return ++ticks; + } void display() const { float progress = (float) ticks / total_ticks; @@ -29,6 +34,7 @@ class ProgressBar { std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); auto time_elapsed = std::chrono::duration_cast(now - start_time).count(); + std::unique_lock lck (mtx); // stdout must be accessed in mutual exclusion std::cout << "["; for (int i = 0; i < bar_width; ++i) {