DYTSrouce/Tool/matlab/include/shared_autonomous/autonomouscodegen_parallel_range.hpp
2024-11-22 23:19:31 +08:00

121 lines
3.1 KiB
C++

/* Copyright 2018 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 AUTONOMOUSCODEGEN_PARALLEL_RANGE_H_
#define AUTONOMOUSCODEGEN_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 autonomous {
/**
* 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 <typename T>
class ParallelRange {
public:
typedef T const_iterator;
typedef uint32_T uint32_Type;
ParallelRange()
: m_end(static_cast<T>(0))
, m_begin(static_cast<T>(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 autonomous
#endif