Bolt  1.3
C++ template library with support for OpenCL
constant_iterator.h
Go to the documentation of this file.
1 /***************************************************************************
2 * © 2012,2014 Advanced Micro Devices, Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 
16 ***************************************************************************/
17 #pragma once
18 #if !defined( BOLT_CL_CONSTANT_ITERATOR_H )
19 #define BOLT_CL_CONSTANT_ITERATOR_H
20 #include "bolt/cl/bolt.h"
22 #include <boost/iterator/iterator_facade.hpp>
23 
29 namespace bolt {
30 namespace cl {
31 
33  : public fancy_iterator_tag
34  { // identifying tag for random-access iterators
35 
36  };
37 
38 
74  template< typename value_type >
75  class constant_iterator: public boost::iterator_facade< constant_iterator< value_type >, value_type,
76  constant_iterator_tag, value_type, int >
77  {
78  public:
79  typedef typename boost::iterator_facade< constant_iterator< value_type >, value_type, constant_iterator_tag,
80  value_type, int >::difference_type difference_type;
82  typedef std::random_access_iterator_tag memory_system;
83  typedef value_type * pointer;
84 
85  struct Payload
86  {
87  value_type m_Value;
88  };
89 
90  // Basic constructor requires a reference to the container and a positional element
91  constant_iterator( value_type init, const control& ctl = control::getDefault( ) ):
92  m_constValue( init ), m_Index( 0 )
93  {
94  const ::cl::CommandQueue& m_commQueue = ctl.getCommandQueue( );
95 
96  // We want to use the context from the passed in commandqueue to initialize our buffer
97  cl_int l_Error = CL_SUCCESS;
98  ::cl::Context l_Context = m_commQueue.getInfo< CL_QUEUE_CONTEXT >( &l_Error );
99  V_OPENCL( l_Error, "device_vector failed to query for the context of the ::cl::CommandQueue object" );
100 
101  m_devMemory = ::cl::Buffer( l_Context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR,
102  1 * sizeof( value_type ),const_cast<value_type *>(&m_constValue) );
103  }
104 
105  // This copy constructor allows an iterator to convert into a const_iterator, but not vica versa
106  template< typename OtherType >
107  constant_iterator( const constant_iterator< OtherType >& rhs ): m_devMemory( rhs.m_devMemory ),
108  m_Index( rhs.m_Index ), m_constValue( rhs.m_constValue )
109  {}
110 
111  // This copy constructor allows an iterator to convert into a const_iterator, but not vica versa
112  constant_iterator< value_type >& operator= ( const constant_iterator< value_type >& rhs )
113  {
114  if( this == &rhs )
115  return *this;
116 
117  m_devMemory = rhs.m_devMemory;
118  m_constValue = rhs.m_constValue;
119  m_Index = rhs.m_Index;
120  return *this;
121  }
122 
123  value_type* getPointer()
124  {
125  return &m_constValue;
126  }
127 
128  const value_type* getPointer() const
129  {
130  return &m_constValue;
131  }
132 
133  constant_iterator< value_type >& operator+= ( const difference_type & n )
134  {
135  advance( n );
136  return *this;
137  }
138 
139  const constant_iterator< value_type > operator+ ( const difference_type & n ) const
140  {
141  constant_iterator< value_type > result( *this );
142  result.advance( n );
143  return result;
144  }
145 
146  const ::cl::Buffer& getBuffer( ) const
147  {
148  return m_devMemory;
149  }
150 
151  const constant_iterator< value_type > & getContainer( ) const
152  {
153  return *this;
154  }
155 
156  const constant_iterator< value_type > & base( ) const
157  {
158  return *this;
159  }
160 
161  Payload gpuPayload( ) const
162  {
163  Payload payload = { m_constValue };
164  return payload;
165  }
166 
167  const difference_type gpuPayloadSize( ) const
168  {
169  return sizeof( Payload );
170  }
171 
172  int setKernelBuffers(int arg_num, ::cl::Kernel &kernel) const
173  {
174  const ::cl::Buffer &buffer = getContainer().getBuffer();
175  kernel.setArg(arg_num, buffer );
176  arg_num++;
177  return arg_num;
178  }
179 
180  difference_type distance_to( const constant_iterator< value_type >& rhs ) const
181  {
182  //return static_cast< typename iterator_facade::difference_type >( 1 );
183  return rhs.m_Index - m_Index;
184  }
185 
186  // Public member variables
187  difference_type m_Index;
188 
189  private:
190  // Implementation detail of boost.iterator
191  friend class boost::iterator_core_access;
192 
193  // Used for templatized copy constructor and the templatized equal operator
194  template < typename > friend class constant_iterator;
195 
196  // For a constant_iterator, do nothing on an advance
197  void advance( difference_type n )
198  {
199  m_Index += n;
200  }
201 
202  void increment( )
203  {
204  advance( 1 );
205  }
206 
207  void decrement( )
208  {
209  advance( -1 );
210  }
211 
212  template< typename OtherType >
213  bool equal( const constant_iterator< OtherType >& rhs ) const
214  {
215  bool sameIndex = (rhs.m_constValue == m_constValue) && (rhs.m_Index == m_Index);
216  return sameIndex;
217  }
218 
219  typename boost::iterator_facade< constant_iterator< value_type >, value_type,
220  constant_iterator_tag, value_type, int >::reference dereference( ) const
221  {
222  return m_constValue;
223  }
224 
225  ::cl::Buffer m_devMemory;
226  value_type m_constValue;
227  };
228  //)
229 
230  // This string represents the device side definition of the constant_iterator template
231  static std::string deviceConstantIterator =
232  std::string("#if !defined(BOLT_CL_CONSTANT_ITERATOR) \n#define BOLT_CL_CONSTANT_ITERATOR \n") +
233  STRINGIFY_CODE(
234  namespace bolt { namespace cl { \n
235  template< typename T > \n
236  class constant_iterator \n
237  { \n
238  public: \n
239  typedef int iterator_category; // device code does not understand std:: tags \n
240  typedef T value_type; \n
241  typedef T base_type; \n
242  typedef size_t difference_type; \n
243  typedef size_t size_type; \n
244  typedef T* pointer; \n
245  typedef T& reference; \n
246 
247  constant_iterator( value_type init ): m_constValue( init ), m_Ptr( 0 ) \n
248  { }; \n
249 
250  void init( global value_type* ptr ) \n
251  { }; \n
252 
253  value_type operator[]( size_type threadID ) const \n
254  { \n
255  return m_constValue; \n
256  } \n
257 
258  value_type operator*( ) const \n
259  { \n
260  return m_constValue; \n
261  } \n
262 
263  value_type m_constValue; \n
264  }; \n
265  } } \n
266  )
267  + std::string("#endif \n");
268 
269  template< typename Type >
270  constant_iterator< Type > make_constant_iterator( Type constValue )
271  {
272  constant_iterator< Type > tmp( constValue );
273  return tmp;
274  }
275 
276 }
277 }
278 
280 BOLT_CREATE_CLCODE( bolt::cl::constant_iterator< int >, bolt::cl::deviceConstantIterator );
281 
285 
286 #endif