/* Copyright 2020 The MathWorks, Inc. */ /** * @file * Open-interval range that can be used for parallel or serial execution. * To fully support code generation, note that this file needs to be fully * compliant with the C++98 standard. */ #ifndef UAVDUBINSCODEGEN_PARALLEL_RANGE_H_ #define UAVDUBINSCODEGEN_PARALLEL_RANGE_H_ // TBB defines a dummy datatype (tbb::split) to differentiate // splitting constructors from all the rest. Splittability is // potentially useful for contexts outside of TBB, so define a dummy // class if TBB isn't available. #if defined(TBB_AVAILABLE) #include "tbb/tbb_stddef.h" #else namespace tbb { typedef struct split { } split; } // namespace tbb #endif namespace uav { /** * An open-interval range [begin, end) that can be used for parallel or * serial execution. * * This implementation follows the "Range Concept" requirements spelled out by * TBB (https://software.intel.com/en-us/node/506143#range_concept), but also * compiles and runs if no TBB is available. */ template class ParallelRange { public: typedef T const_iterator; typedef uint32_T uint32_Type; ParallelRange() : m_end(static_cast(0)) , m_begin(static_cast(0)) , m_grainSize(1) { } /** * Construct range over the half-open interval [begin,end), with the given * grain size. * * @param begin Start of range (inclusive) * @param end End of range (exclusive, open interval) * @param grainSize Allow subdivision of the full range based on the grain size. */ ParallelRange(T begin, T end, uint32_Type grainSize = 1) : m_end(end) , m_begin(begin) , m_grainSize(grainSize) { } /** * Inclusive lower bound on range. */ const_iterator begin() const { return m_begin; } /** * Exclusive upper bound on range. */ const_iterator end() const { return m_end; } uint32_Type size() const { return uint32_Type(m_end - m_begin); } uint32_Type grainsize() const { return m_grainSize; } //------------------------------------------------------------------------ // Methods that implement Range concept //------------------------------------------------------------------------ /// True if range is empty. boolean_T empty() const { return !(m_begin < m_end); } /// True if range is divisible. boolean_T is_divisible() const { return m_grainSize < size(); } /// Split range. ParallelRange(ParallelRange& r, tbb::split) : m_end(r.m_end) , m_begin(splitRange(r)) , m_grainSize(r.m_grainSize) { } private: T m_end; ///< End of range (exclusive) T m_begin; ///< Start of range (inclusive) uint32_Type m_grainSize; ///< Grain size used for subdivision /// Auxiliary function used by forking constructor. static T splitRange(ParallelRange& r) { T middle = r.m_begin + (r.m_end - r.m_begin) / 2u; r.m_end = middle; return middle; } }; } // namespace uav #endif