Created
April 2, 2012 05:09
-
-
Save yohhoy/2280921 to your computer and use it in GitHub Desktop.
Mockup implementation of TBB
This file contains hidden or 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
| /* | |
| * Mockup implementation of Threading Building Blocks(TBB) library | |
| * | |
| * (C) Copyright yohhoy 2012. | |
| * Distributed under the Boost Software License, Version 1.0. | |
| * (See copy at http://www.boost.org/LICENSE_1_0.txt) | |
| * | |
| * Support: | |
| * - Range concept (except `blocked_range3d') | |
| * - Parallel algorithms (except `pipeline'/`parallel_pipeline') | |
| * - template class `atomic<T>' | |
| * - Timing classes (sloppy implementation with `std::time()') | |
| * - class `task_scheduler_init' | |
| */ | |
| #ifndef TBB_STUB_H_INCLUDED_ | |
| #define TBB_STUB_H_INCLUDED_ | |
| #include <cstddef> | |
| #include <ctime> | |
| #include <deque> | |
| #include <algorithm> | |
| #include <iterator> | |
| // Version Information | |
| #define TBB_INTERFACE_VERSION 0 | |
| #define TBB_INTERFACE_VERSION_MAJOR 0 | |
| #define TBB_COMPATIBLE_INTERFACE_VERSION 0 | |
| extern "C" inline int TBB_runtime_interface_version() { return 0; } | |
| namespace tbb { | |
| // Split tag | |
| class split {}; | |
| // Range Concept | |
| template<typename Value> | |
| class blocked_range { | |
| public: | |
| typedef std::size_t size_type; | |
| typedef Value const_iterator; | |
| blocked_range(Value begin, Value end, size_type grainsize = 1) | |
| : begin_(begin), end_(end), grainsize_(grainsize) {} | |
| // blocked_range(blocked_range& range, split); | |
| size_type size() const { return end_ - begin_; } | |
| bool empty() const { return begin < end_; } | |
| size_type grainsize() const { return grainsize_; } | |
| bool is_divisible() const { return false; } | |
| const_iterator begin() const { return begin_; } | |
| const_iterator end() const { return end_; } | |
| private: | |
| Value begin_, end_; | |
| size_type grainsize_; | |
| }; | |
| template<typename RowValue, typename ColValue = RowValue> | |
| class blocked_range2d { | |
| public: | |
| typedef blocked_range<RowValue> row_range_type; | |
| typedef blocked_range<ColValue> col_range_type; | |
| blocked_range2d(RowValue row_begin, RowValue row_end, typename row_range_type::size_type row_grainsize, | |
| ColValue col_begin, ColValue col_end, typename col_range_type::size_type col_grainsize) | |
| : row_(row_begin, row_end, row_grainsize), col_(col_begin, col_end, col_grainsize) {} | |
| blocked_range2d(RowValue row_begin, RowValue row_end, ColValue col_begin, ColValue col_end) | |
| : row_(row_begin, row_end), col_(col_begin, col_end) {} | |
| // blocked_range2d( blocked_range2d& r, split ); | |
| bool empty() const { return row_.empty() || col_.empty(); } | |
| bool is_divisible() const { return false; } | |
| const row_range_type& rows() const { return row_; } | |
| const col_range_type& cols() const { return col_; } | |
| private: | |
| row_range_type row_; | |
| col_range_type col_; | |
| }; | |
| // Partitioners | |
| class auto_partitioner {}; | |
| class affinity_partitioner {}; | |
| class simple_partitioner {}; | |
| // parallel_for Template | |
| template<class Index, class Func> | |
| void parallel_for(Index first, Index last, const Func& func) | |
| { | |
| parallel_for(first, last, static_cast<Index>(1), func); | |
| } | |
| template<class Index, class Func> | |
| void parallel_for(Index first, Index last, Index step, const Func& func) | |
| { | |
| for (; first < last; first += step) | |
| func(first); | |
| } | |
| template<class Range, class Body> | |
| void parallel_for(const Range& range, const Body& body) | |
| { | |
| body(range); | |
| } | |
| template<class Range, class Body> | |
| void parallel_for(const Range& range, const Body& body, const auto_partitioner&) | |
| { parallel_for(range, body); } | |
| template<class Range, class Body> | |
| void parallel_for(const Range& range, const Body& body, const affinity_partitioner&) | |
| { parallel_for(range, body); } | |
| template<class Range, class Body> | |
| void parallel_for(const Range& range, const Body& body, const simple_partitioner&) | |
| { parallel_for(range, body); } | |
| // parallel_reduce Template | |
| template<typename Range, typename Value, typename Func, typename Reduction> | |
| Value parallel_reduce(const Range& range, const Value& identity, const Func& func, const Reduction&) | |
| { | |
| return func(range, identity); | |
| } | |
| template<typename Range, typename Value, typename Func, typename Reduction> | |
| Value parallel_reduce(const Range& range, const Value& identity, const Func& func, const Reduction&, const auto_partitioner&) | |
| { return parallel_reduce(range, identity, func); } | |
| template<typename Range, typename Value, typename Func, typename Reduction> | |
| Value parallel_reduce(const Range& range, const Value& identity, const Func& func, const Reduction&, const affinity_partitioner&) | |
| { return parallel_reduce(range, identity, func); } | |
| template<typename Range, typename Value, typename Func, typename Reduction> | |
| Value parallel_reduce(const Range& range, const Value& identity, const Func& func, const Reduction&, const simple_partitioner&) | |
| { return parallel_reduce(range, identity, func); } | |
| template<typename Range, typename Body> | |
| void parallel_reduce(const Range& range, Body& body) | |
| { | |
| body(range); | |
| } | |
| template<typename Range, typename Body> | |
| void parallel_reduce(const Range& range, Body& body, const auto_partitioner&) | |
| { parallel_reduce(range, body); } | |
| template<typename Range, typename Body> | |
| void parallel_reduce(const Range& range, Body& body, const affinity_partitioner&) | |
| { parallel_reduce(range, body); } | |
| template<typename Range, typename Body> | |
| void parallel_reduce(const Range& range, Body& body, const simple_partitioner&) | |
| { parallel_reduce(range, body); } | |
| // parallel_scan Template | |
| struct pre_scan_tag { | |
| static bool is_final_scan() { return false; } | |
| }; | |
| struct final_scan_tag { | |
| static bool is_final_scan() { return true; } | |
| }; | |
| template<typename Range, typename Body> | |
| void parallel_scan(const Range& range, Body& body) | |
| { | |
| body(range, pre_scan_tag()); | |
| body(range, final_scan_tag()); | |
| } | |
| template<typename Range, typename Body> | |
| void parallel_scan(const Range& range, Body& body, const auto_partitioner&) | |
| { parallel_scan(range, body); } | |
| template<typename Range, typename Body> | |
| void parallel_scan(const Range& range, Body& body, const simple_partitioner&) | |
| { parallel_scan(range, body); } | |
| // parallel_do Template | |
| template<typename Item> | |
| struct parallel_do_feeder { | |
| void add(const Item& item) { queue_.push_back(item); } | |
| /*internal:*/ | |
| parallel_do_feeder(std::deque<Item>& queue) : queue_(queue) {} | |
| std::deque<Item>& queue_; | |
| }; | |
| template<typename InputIterator, typename Body> | |
| void parallel_do(InputIterator first, InputIterator last, Body body) | |
| { | |
| typedef typename std::iterator_traits<InputIterator>::value_type Item; | |
| std::deque<Item> queue; | |
| parallel_do_feeder<Item> feeder(queue); | |
| for (; first != last; ++first) | |
| body(*first, feeder); | |
| for (; !queue.empty(); queue.pop_front()) | |
| body(queue.front(), feeder); | |
| } | |
| // parallel_for_each Template | |
| template<typename InputIterator, typename Func> | |
| void parallel_for_each(InputIterator first, InputIterator last, const Func& func) | |
| { | |
| for (; first != last; ++first) | |
| func(*first); | |
| } | |
| // parallel_sort Template | |
| template<typename RandomAccessIterator> | |
| void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end) | |
| { | |
| std::sort(begin, end); | |
| } | |
| template<typename RandomAccessIterator, typename Compare> | |
| void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end, const Compare& comp) | |
| { | |
| std::sort(begin, end, comp); | |
| } | |
| // parallel_invoke Template | |
| template<typename Func0, typename Func1> | |
| void parallel_invoke(const Func0& f0, const Func1& f1) | |
| { | |
| f0(); f1(); | |
| } | |
| template<typename Func0, typename Func1, typename Func2> | |
| void parallel_invoke(const Func0& f0, const Func1& f1, const Func2& f2) | |
| { | |
| f0(); f1(); f2(); | |
| } | |
| template<typename Func0, typename Func1, typename Func2, typename Func3> | |
| void parallel_invoke(const Func0& f0, const Func1& f1, const Func2& f2, const Func3& f3) | |
| { | |
| f0(); f1(); f2(); f3(); | |
| } | |
| //...Do you need more overloads? Do it YOURSELF. | |
| // atomic Template Class | |
| enum memory_semantics { acquire, release }; | |
| template <class T> | |
| struct atomic { | |
| typedef T value_type; | |
| // NOTE: Actually, all operations are NOT atomic. | |
| template<memory_semantics M> | |
| value_type compare_and_swap(value_type new_value, value_type comparand) | |
| { value_type s = v_; v_ = (v_ == comparand) ? new_value : v_; return s; } | |
| value_type compare_and_swap(value_type new_value, value_type comparand) | |
| { value_type s = v_; v_ = (v_ == comparand) ? new_value : v_; return s; } | |
| template<memory_semantics M> | |
| value_type fetch_and_store(value_type new_value) | |
| { value_type s = v_; v_ = new_value; return s; } | |
| value_type fetch_and_store(value_type new_value) | |
| { value_type s = v_; v_ = new_value; return s; } | |
| operator value_type() const { return v_; } | |
| value_type operator=(value_type new_value) { return v_ = new_value; } | |
| atomic<T>& operator=(const atomic<T>& value) { v_ = value.v_; return *this; } | |
| template<memory_semantics M> | |
| value_type fetch_and_add(value_type addend) | |
| { value_type s = v_; v_ += addend; return s; } | |
| value_type fetch_and_add(value_type addend) | |
| { value_type s = v_; v_ += addend; return s; } | |
| template<memory_semantics M> | |
| value_type fetch_and_increment() { return v_++; } | |
| value_type fetch_and_increment() { return v_++; } | |
| template<memory_semantics M> | |
| value_type fetch_and_decrement() { return v_--; } | |
| value_type fetch_and_decrement() { return v_--; } | |
| value_type operator+=(value_type x) { return v_ -= x; } | |
| value_type operator-=(value_type x) { return v_ -= x; } | |
| value_type operator++() { return ++v_; } | |
| value_type operator++(int) { return v_++; } | |
| value_type operator--() { return ++v_; } | |
| value_type operator--(int) { return v_--; } | |
| private: | |
| value_type v_; | |
| }; | |
| // tick_count Class | |
| class tick_count { | |
| public: | |
| class interval_t; | |
| static tick_count now() { return tick_count(); } | |
| friend tick_count::interval_t operator-(const tick_count&, const tick_count&); | |
| private: | |
| tick_count() : tm_(std::time(0)) {} | |
| tick_count(std::time_t t) : tm_(t) {} | |
| std::time_t tm_; | |
| }; | |
| // tick_count::interval_t Class | |
| class tick_count::interval_t { | |
| public: | |
| interval_t() : d_(0) {} | |
| explicit interval_t(double sec) : d_(sec) {} | |
| double seconds() const { return d_; } | |
| interval_t operator+=(const interval_t& i) { return interval_t(d_ + i.d_); } | |
| interval_t operator-=(const interval_t& i) { return interval_t(d_ - i.d_); } | |
| friend tick_count::interval_t operator+(const tick_count::interval_t& i, const tick_count::interval_t& j) | |
| { return tick_count::interval_t(i.d_ + j.d_); } | |
| friend tick_count::interval_t operator-(const tick_count::interval_t& i, const tick_count::interval_t& j) | |
| { return tick_count::interval_t(i.d_ - j.d_); } | |
| private: | |
| double d_; | |
| }; | |
| inline tick_count::interval_t operator-(const tick_count& t1, const tick_count& t0) | |
| { | |
| return tick_count::interval_t(static_cast<double>(t1.tm_ - t0.tm_)); | |
| } | |
| // task_scheduler_init Class | |
| class task_scheduler_init | |
| { | |
| public: | |
| typedef std::size_t stack_size_type; | |
| static const int automatic = 0; | |
| static const int deferred = -1; | |
| task_scheduler_init(int max_threads = automatic, stack_size_type /*thread_stack_size*/ = 0) | |
| : active_(max_threads != deferred) {} | |
| void initialize(int max_threads = automatic) { active_ = (max_threads != deferred); } | |
| void terminate() { active_ = false; } | |
| bool is_active() const { return active_; } | |
| static int default_num_threads() { return 1; } | |
| private: | |
| bool active_; | |
| }; | |
| } // namespace tbb | |
| #endif // TBB_STUB_H_INCLUDED_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment