c-resources/CPlusPlus20ForProgrammers-m.../examples/ch17/fig17_12/async.cpp

153 lines
5.0 KiB
C++

// Fig. 17.12: async.cpp
// Prime-factorization tasks performed in separate threads
#include <cmath>
#include <fmt/format.h>
#include <future> // std::async
#include <iostream>
#include <sstream>
#include <string>
#include <tuple>
#include <vector>
// get current thread's ID as a string
std::string id() {
std::ostringstream out;
out << std::this_thread::get_id();
return out.str();
}
// type alias for vector of factor/count pairs
using Factors = std::vector<std::pair<long long, int>>;
// type alias for a tuple containing a task name,
// a number, whether the number is prime and its factors
using FactorResults = std::tuple<std::string, long long, bool, Factors>;
// performs prime factorization
FactorResults getFactors(std::string name, long long number) {
std::cout << fmt::format(
"{}: Thread {} executing getFactors for {}\n", name, id(), number);
long long originalNumber{number}; // copy to place in FactorResults
Factors factors; // vector of factor/count pairs
// lambda that divides number by a factor and stores factor/count
auto factorCount{
[&](int factor) {
int count{0}; // how many times number is divisible by factor
// count how many times number is divisible by factor
while (number % factor == 0) {
++count;
number /= factor;
}
// store pair containing the factor and its count
if (count > 0) {
factors.push_back({factor, count});
}
}
};
factorCount(2); // count how many times number is divisible by 2
// number is now odd; store each factor and its count
for (int i{3}; i <= std::sqrt(number); i += 2) {
factorCount(i); // count how many times number is divisible by i
}
// add last prime factor
if (number > 2) {
factors.push_back({number, 1});
}
bool isPrime{factors.size() == 1 && get<int>(factors[0]) == 1};
// initialize the FactorResults object returned by getFactors
return {name, originalNumber, isPrime, factors};
}
// multiply the factors and confirm they reproduce number
void proveFactors(long long number, const Factors& factors) {
long long proof{1};
// for each factor/count pair, unpack it then multiply proof
// by factor the number of times specified by count
for (const auto& [factor, count] : factors) {
for (int i{0}; i < count; ++i) {
proof *= factor;
}
}
// confirm proof and number are equal
if (proof == number) {
std::cout << fmt::format(
"\nProduct of factors matches original value ({})\n", proof);
}
else {
std::cout << fmt::format("\n{} != {}\n", proof, number);
}
}
// show a task's FactorResults
void displayResults(const FactorResults& results) {
// unpack results into name (std::string), number (long long),
// isPrime (bool) and factors (Factors)
const auto& [name, number, isPrime, factors] {results};
std::cout << fmt::format("\n{} results:\n", name);
// display whether value is prime
if (isPrime) {
std::cout << fmt::format("{} is prime\n", number);
}
else { // display prime factors
std::cout << fmt::format("{}'s prime factors:\n\n", number);
std::cout << fmt::format("{:<12}{:<8}\n", "Factor", "Count");
for (const auto& [factor, count] : factors) {
std::cout << fmt::format("{:<12}{:<8}\n", factor, count);
}
}
// if not prime, prove that factors produce the original number
if (!isPrime) {
proveFactors(number, factors);
}
}
int main() {
std::cout << "MAIN LAUNCHING TASKS\n";
auto future1{std::async(std::launch::async,
getFactors, "Task 1", 1016669006116682993)}; // not prime
auto future2{std::async(std::launch::async,
getFactors, "Task 2", 1000000000000000003)}; // prime
std::cout << "\nWAITING FOR TASK RESULTS\n";
// wait for results from each task, then display the results
displayResults(future1.get());
displayResults(future2.get());
std::cout << "\nMAIN ENDS\n";
}
/************************************************************************
* (C) Copyright 1992-2022 by Deitel & Associates, Inc. and *
* Pearson Education, Inc. All Rights Reserved. *
* *
* DISCLAIMER: The authors and publisher of this book have used their *
* best efforts in preparing the book. These efforts include the *
* development, research, and testing of the theories and programs *
* to determine their effectiveness. The authors and publisher make *
* no warranty of any kind, expressed or implied, with regard to these *
* programs or to the documentation contained in these books. The *
* authors and publisher shall not be liable in any event for *
* incidental or consequential damages in connection with, or arising *
* out of, the furnishing, performance, or use of these programs. *
***********************************************************************/