Last active
October 10, 2018 16:52
-
-
Save daniel-j-h/d8f9b1e441c0ac78db86 to your computer and use it in GitHub Desktop.
C++ Intel Threading Building Blocks task scheduling observer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <vector> | |
#include <iterator> | |
#include <algorithm> | |
#include <mutex> | |
#include <thread> | |
#include "tbb/task_scheduler_observer.h" | |
#include "tbb/task_scheduler_init.h" | |
#include "tbb/blocked_range.h" | |
#include "tbb/parallel_for.h" | |
// clang++ -std=c++11 -O2 -ltbb main.cc | |
// g++ -std=c++11 -O2 -ltbb main.cc | |
// ./a.out | |
// synchronizing concurrent acceseses to any resource | |
template <typename T> | |
class monitor { | |
private: | |
/* mutable */ T t; | |
mutable std::mutex m; | |
public: | |
monitor(T t_ = T{}) : t(t_) | |
{ | |
} | |
template <typename F> | |
auto operator()(F f) const -> decltype(f(t)) | |
{ | |
std::lock_guard<std::mutex> _{m}; | |
return f(t); | |
} | |
}; | |
// thread safe cout | |
static monitor<std::ostream&> out{std::cout}; | |
// scheduler hooks | |
class task_observer final : public tbb::task_scheduler_observer { | |
public: | |
task_observer() | |
{ | |
observe(true); | |
} | |
void on_scheduler_entry(bool) | |
{ | |
out([&](std::ostream& out) { out << "\n\n[" << std::this_thread::get_id() << "]:" << std::endl; }); | |
} | |
void on_scheduler_exit(bool) | |
{ | |
out([&](std::ostream& out) { out << "\n\n[" << std::this_thread::get_id() << "]" << std::endl; }); | |
} | |
}; | |
int main(int argc, char** argv) | |
{ | |
tbb::task_scheduler_init sentry{4}; | |
task_observer observer; | |
std::vector<int> vec(200); | |
std::iota(std::begin(vec), std::end(vec), 0); | |
using range_t = tbb::blocked_range<decltype(vec)::iterator>; | |
auto range = range_t{std::begin(vec), std::end(vec)}; | |
tbb::parallel_for(range, [](range_t& range) { | |
out([&](std::ostream& out) { | |
// at least one item in range, end - 1 is safe to dereference | |
out << "[" << *std::begin(range) << ',' << *(--std::end(range)) << "] "; | |
}); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment