File indexing completed on 2025-01-18 09:30:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_COMPUTE_ITERATOR_BUFFER_ITERATOR_HPP
0012 #define BOOST_COMPUTE_ITERATOR_BUFFER_ITERATOR_HPP
0013
0014 #include <cstddef>
0015 #include <iterator>
0016
0017 #include <boost/config.hpp>
0018 #include <boost/type_traits.hpp>
0019 #include <boost/static_assert.hpp>
0020 #include <boost/utility/enable_if.hpp>
0021 #include <boost/iterator/iterator_facade.hpp>
0022
0023 #include <boost/compute/buffer.hpp>
0024 #include <boost/compute/detail/buffer_value.hpp>
0025 #include <boost/compute/detail/is_buffer_iterator.hpp>
0026 #include <boost/compute/detail/meta_kernel.hpp>
0027 #include <boost/compute/detail/read_write_single_value.hpp>
0028 #include <boost/compute/type_traits/is_device_iterator.hpp>
0029
0030 namespace boost {
0031 namespace compute {
0032
0033
0034 template<class T> class buffer_iterator;
0035
0036 namespace detail {
0037
0038
0039
0040 template<class T>
0041 class buffer_iterator_base
0042 {
0043 public:
0044 typedef ::boost::iterator_facade<
0045 ::boost::compute::buffer_iterator<T>,
0046 T,
0047 ::std::random_access_iterator_tag,
0048 ::boost::compute::detail::buffer_value<T>
0049 > type;
0050 };
0051
0052 template<class T, class IndexExpr>
0053 struct buffer_iterator_index_expr
0054 {
0055 typedef T result_type;
0056
0057 buffer_iterator_index_expr(const buffer &buffer,
0058 size_t index,
0059 const memory_object::address_space address_space,
0060 const IndexExpr &expr)
0061 : m_buffer(buffer.get(), false),
0062 m_index(index),
0063 m_address_space(address_space),
0064 m_expr(expr)
0065 {
0066 }
0067
0068 buffer_iterator_index_expr(const buffer_iterator_index_expr& other)
0069 : m_buffer(other.m_buffer.get(), false),
0070 m_index(other.m_index),
0071 m_address_space(other.m_address_space),
0072 m_expr(other.m_expr)
0073 {
0074 }
0075
0076 ~buffer_iterator_index_expr()
0077 {
0078
0079
0080 m_buffer.get() = 0;
0081 }
0082
0083 operator T() const
0084 {
0085 BOOST_STATIC_ASSERT_MSG(boost::is_integral<IndexExpr>::value,
0086 "Index expression must be integral");
0087
0088 return buffer_value<T>(m_buffer, size_t(m_expr) * sizeof(T));
0089 }
0090
0091 const buffer m_buffer;
0092 const size_t m_index;
0093 const memory_object::address_space m_address_space;
0094 const IndexExpr m_expr;
0095 };
0096
0097 template<class T, class IndexExpr>
0098 inline meta_kernel& operator<<(meta_kernel &kernel,
0099 const buffer_iterator_index_expr<T, IndexExpr> &expr)
0100 {
0101 if(expr.m_index == 0){
0102 return kernel <<
0103 kernel.get_buffer_identifier<T>(expr.m_buffer, expr.m_address_space) <<
0104 '[' << expr.m_expr << ']';
0105 }
0106 else {
0107 return kernel <<
0108 kernel.get_buffer_identifier<T>(expr.m_buffer, expr.m_address_space) <<
0109 '[' << uint_(expr.m_index) << "+(" << expr.m_expr << ")]";
0110 }
0111 }
0112
0113 }
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135 template<class T>
0136 class buffer_iterator : public detail::buffer_iterator_base<T>::type
0137 {
0138 public:
0139 typedef typename detail::buffer_iterator_base<T>::type super_type;
0140 typedef typename super_type::reference reference;
0141 typedef typename super_type::difference_type difference_type;
0142
0143 buffer_iterator()
0144 : m_index(0)
0145 {
0146 }
0147
0148 buffer_iterator(const buffer &buffer, size_t index)
0149 : m_buffer(buffer.get(), false),
0150 m_index(index)
0151 {
0152 }
0153
0154 buffer_iterator(const buffer_iterator<T> &other)
0155 : m_buffer(other.m_buffer.get(), false),
0156 m_index(other.m_index)
0157 {
0158 }
0159
0160 buffer_iterator<T>& operator=(const buffer_iterator<T> &other)
0161 {
0162 if(this != &other){
0163 m_buffer.get() = other.m_buffer.get();
0164 m_index = other.m_index;
0165 }
0166
0167 return *this;
0168 }
0169
0170 ~buffer_iterator()
0171 {
0172
0173
0174 m_buffer.get() = 0;
0175 }
0176
0177 const buffer& get_buffer() const
0178 {
0179 return m_buffer;
0180 }
0181
0182 size_t get_index() const
0183 {
0184 return m_index;
0185 }
0186
0187 T read(command_queue &queue) const
0188 {
0189 BOOST_ASSERT(m_buffer.get());
0190 BOOST_ASSERT(m_index < m_buffer.size() / sizeof(T));
0191
0192 return detail::read_single_value<T>(m_buffer, m_index, queue);
0193 }
0194
0195 void write(const T &value, command_queue &queue)
0196 {
0197 BOOST_ASSERT(m_buffer.get());
0198 BOOST_ASSERT(m_index < m_buffer.size() / sizeof(T));
0199
0200 detail::write_single_value<T>(value, m_buffer, m_index, queue);
0201 }
0202
0203
0204 template<class Expr>
0205 detail::buffer_iterator_index_expr<T, Expr>
0206 operator[](const Expr &expr) const
0207 {
0208 BOOST_ASSERT(m_buffer.get());
0209
0210 return detail::buffer_iterator_index_expr<T, Expr>(
0211 m_buffer, m_index, memory_object::global_memory, expr
0212 );
0213 }
0214
0215 private:
0216 friend class ::boost::iterator_core_access;
0217
0218
0219 reference dereference() const
0220 {
0221 return detail::buffer_value<T>(m_buffer, m_index * sizeof(T));
0222 }
0223
0224
0225 bool equal(const buffer_iterator<T> &other) const
0226 {
0227 return m_buffer.get() == other.m_buffer.get() &&
0228 m_index == other.m_index;
0229 }
0230
0231
0232 void increment()
0233 {
0234 m_index++;
0235 }
0236
0237
0238 void decrement()
0239 {
0240 m_index--;
0241 }
0242
0243
0244 void advance(difference_type n)
0245 {
0246 m_index = static_cast<size_t>(static_cast<difference_type>(m_index) + n);
0247 }
0248
0249
0250 difference_type distance_to(const buffer_iterator<T> &other) const
0251 {
0252 return static_cast<difference_type>(other.m_index - m_index);
0253 }
0254
0255 private:
0256 const buffer m_buffer;
0257 size_t m_index;
0258 };
0259
0260
0261
0262
0263
0264
0265
0266 template<class T>
0267 inline buffer_iterator<T>
0268 make_buffer_iterator(const buffer &buffer, size_t index = 0)
0269 {
0270 return buffer_iterator<T>(buffer, index);
0271 }
0272
0273
0274 template<class T>
0275 struct is_device_iterator<buffer_iterator<T> > : boost::true_type {};
0276
0277 namespace detail {
0278
0279
0280 template<class Iterator>
0281 struct is_buffer_iterator<
0282 Iterator,
0283 typename boost::enable_if<
0284 boost::is_same<
0285 buffer_iterator<typename Iterator::value_type>,
0286 typename boost::remove_const<Iterator>::type
0287 >
0288 >::type
0289 > : public boost::true_type {};
0290
0291 }
0292 }
0293 }
0294
0295 #endif