Skip to content

Instantly share code, notes, and snippets.

@ot32em
Last active September 3, 2015 02:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ot32em/e677b9724af12859beb9 to your computer and use it in GitHub Desktop.
Save ot32em/e677b9724af12859beb9 to your computer and use it in GitHub Desktop.
A brief usage of `sequential`, `thread`, `async`, `packaged_task`, and `promise`.
#include <iostream>
#include <vector>
#include <numeric>
#include <thread>
#include <chrono>
#include <random>
#include <future>
namespace tool
{
std::vector<int> gen_vector(std::size_t s)
{
std::random_device eng;
std::uniform_int_distribution<> gen(0, 100);
std::vector<int> vec(s);
std::generate(vec.begin(), vec.end(), [&]() { return gen(eng); });
return vec;
}
std::chrono::milliseconds elapsed_ms(std::chrono::steady_clock::time_point tp)
{
auto elapsed = std::chrono::steady_clock::now() - tp;
return std::chrono::duration_cast<std::chrono::milliseconds>(elapsed);
}
struct ScopeTimer
{
using clock = std::chrono::steady_clock;
clock::time_point m_tp;
ScopeTimer(){
std::cout << "Start calculating: " << std::endl;
m_tp = clock::now();
}
~ScopeTimer(){
const auto ms = elapsed_ms(m_tp).count();
std::cout << "End of calculating: " << ms << " ms" << std::endl;
}
};
}
int long_time_sum(const std::vector<int>& vec)
{
std::this_thread::sleep_for(std::chrono::seconds(1));
return std::accumulate(vec.begin(), vec.end(), 0, [](int a, int b) {
return a + b;
});
}
void sequential(const std::vector<std::vector<int>>& src)
{
tool::ScopeTimer timer;
for (const auto& vec : src)
{
std::cout << long_time_sum(vec) << std::endl;
}
}
void concurrent_byref(const std::vector<std::vector<int>>& src)
{
tool::ScopeTimer timer;
auto lambda = [](const std::vector<int>& vec, int& result) {
result = long_time_sum(vec);
};
// Dispatch
std::vector<std::thread> ts;
std::vector<int> rets(src.size());
for (std::size_t i = 0; i < src.size(); i++)
{
ts.emplace_back(lambda, std::cref(src[i]), std::ref(rets[i]));
}
// Output
for (std::size_t i = 0; i < src.size(); i++)
{
ts[i].join();
std::cout << rets[i] << std::endl;
}
}
void concurrent_async(const std::vector<std::vector<int>>& src)
{
tool::ScopeTimer timer;
// Dispatch
std::vector<std::future<int>> fs;
for (const auto& vec : src)
{
fs.push_back(std::async(long_time_sum, std::cref(vec)));
}
// Output
for (auto& f : fs)
{
std::cout << f.get() << std::endl;
}
}
void concurrent_packaged(const std::vector<std::vector<int>>& src)
{
tool::ScopeTimer timer;
// Dispatch
std::vector<std::future<int>> fs;
for (const auto& vec: src)
{
std::packaged_task<decltype(long_time_sum)> task(long_time_sum);
fs.push_back(task.get_future());
std::thread(std::move(task), std::cref(vec)).detach();
}
// Output
for (auto& f : fs)
{
std::cout << f.get() << std::endl;
}
}
void concurrent_promise(const std::vector<std::vector<int>>& src)
{
tool::ScopeTimer timer;
auto lambda = [](const std::vector<int>& vec, std::promise<int>& p) {
try {
auto ret = long_time_sum(vec);
p.set_value(ret);
}
catch (...)
{
p.set_exception(std::current_exception());
}
};
// Dispatch
std::vector<std::promise<int>> ps(src.size());
std::vector<std::future<int>> fs;
for (std::size_t i = 0; i < src.size(); i++)
{
fs.push_back(ps[i].get_future());
std::thread(lambda, std::cref(src[i]), std::ref(ps[i])).detach();
}
// Output
for (auto& f : fs)
{
std::cout << f.get() << std::endl;
}
}
int main()
{
std::vector<std::vector<int>> src = {
tool::gen_vector(100),
tool::gen_vector(100),
tool::gen_vector(100),
tool::gen_vector(100)
};
sequential(src);
concurrent_async(src);
concurrent_byref(src);
concurrent_packaged(src);
concurrent_promise(src);
std::cin.ignore();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment