Bolt  1.1
C++ template library with support for OpenCL
constant_iterator.h
Go to the documentation of this file.
1 /***************************************************************************
2 * Copyright 2012 - 2013 Advanced Micro Devices, Inc.
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  // This represents the host side definition of the constant_iterator template
38  //BOLT_TEMPLATE_FUNCTOR3( constant_iterator, int, float, double,
39  template< typename value_type >
40  class constant_iterator: public boost::iterator_facade< constant_iterator< value_type >, value_type,
41  constant_iterator_tag, value_type, int >
42  {
43  public:
44  typedef typename boost::iterator_facade< constant_iterator< value_type >, value_type,
45  constant_iterator_tag, value_type, int >::difference_type difference_type;
46 
47 
48  struct Payload
49  {
50  value_type m_Value;
51  };
52 
53  // Basic constructor requires a reference to the container and a positional element
54  constant_iterator( value_type init, const control& ctl = control::getDefault( ) ):
55  m_constValue( init ), m_Index( 0 )
56  {
57  const ::cl::CommandQueue& m_commQueue = ctl.getCommandQueue( );
58 
59  // We want to use the context from the passed in commandqueue to initialize our buffer
60  cl_int l_Error = CL_SUCCESS;
61  ::cl::Context l_Context = m_commQueue.getInfo< CL_QUEUE_CONTEXT >( &l_Error );
62  V_OPENCL( l_Error, "device_vector failed to query for the context of the ::cl::CommandQueue object" );
63 
64  m_devMemory = ::cl::Buffer( l_Context, CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR,
65  1 * sizeof( value_type ),const_cast<value_type *>(&m_constValue) );
66  }
67 
68  // This copy constructor allows an iterator to convert into a const_iterator, but not vica versa
69  template< typename OtherType >
70  constant_iterator( const constant_iterator< OtherType >& rhs ): m_devMemory( rhs.m_devMemory ),
71  m_Index( rhs.m_Index ), m_constValue( rhs.m_constValue )
72  {}
73 
74  // This copy constructor allows an iterator to convert into a const_iterator, but not vica versa
75  constant_iterator< value_type >& operator= ( const constant_iterator< value_type >& rhs )
76  {
77  if( this == &rhs )
78  return *this;
79 
80  m_devMemory = rhs.m_devMemory;
81  m_constValue = rhs.m_constValue;
82  m_Index = rhs.m_Index;
83  return *this;
84  }
85 
86  constant_iterator< value_type >& operator+= ( const difference_type & n )
87  {
88  advance( n );
89  return *this;
90  }
91 
92  const constant_iterator< value_type > operator+ ( const difference_type & n ) const
93  {
94  constant_iterator< value_type > result( *this );
95  result.advance( n );
96  return result;
97  }
98 
99  const ::cl::Buffer& getBuffer( ) const
100  {
101  return m_devMemory;
102  }
103 
104  const constant_iterator< value_type > & getContainer( ) const
105  {
106  return *this;
107  }
108 
109  Payload gpuPayload( ) const
110  {
111  Payload payload = { m_constValue };
112  return payload;
113  }
114 
115  const difference_type gpuPayloadSize( ) const
116  {
117  return sizeof( Payload );
118  }
119 
120  difference_type distance_to( const constant_iterator< value_type >& rhs ) const
121  {
122  //return static_cast< typename iterator_facade::difference_type >( 1 );
123  return rhs.m_Index - m_Index;
124  }
125 
126  // Public member variables
127  difference_type m_Index;
128 
129  private:
130  // Implementation detail of boost.iterator
131  friend class boost::iterator_core_access;
132 
133  // Used for templatized copy constructor and the templatized equal operator
134  template < typename > friend class constant_iterator;
135 
136  // For a constant_iterator, do nothing on an advance
137  void advance( difference_type n )
138  {
139  m_Index += n;
140  }
141 
142  void increment( )
143  {
144  advance( 1 );
145  }
146 
147  void decrement( )
148  {
149  advance( -1 );
150  }
151 
152  template< typename OtherType >
153  bool equal( const constant_iterator< OtherType >& rhs ) const
154  {
155  bool sameIndex = (rhs.m_constValue == m_constValue) && (rhs.m_Index == m_Index);
156 
157  return sameIndex;
158  }
159 
160  typename boost::iterator_facade< constant_iterator< value_type >, value_type,
161  constant_iterator_tag, value_type, int >::reference dereference( ) const
162  {
163  return m_constValue;
164  }
165 
166  ::cl::Buffer m_devMemory;
167  value_type m_constValue;
168  };
169  //)
170 
171  // This string represents the device side definition of the constant_iterator template
172  static std::string deviceConstantIterator = STRINGIFY_CODE(
173  namespace bolt { namespace cl { \n
174  template< typename T > \n
175  class constant_iterator \n
176  { \n
177  public: \n
178  typedef int iterator_category; // device code does not understand std:: tags \n
179  typedef T value_type; \n
180  typedef size_t difference_type; \n
181  typedef size_t size_type; \n
182  typedef T* pointer; \n
183  typedef T& reference; \n
184 
185  constant_iterator( value_type init ): m_constValue( init ), m_Ptr( 0 ) \n
186  { }; \n
187 
188  void init( global value_type* ptr ) \n
189  { }; \n
190 
191  value_type operator[]( size_type threadID ) const \n
192  { \n
193  return m_constValue; \n
194  } \n
195 
196  value_type operator*( ) const \n
197  { \n
198  return m_constValue; \n
199  } \n
200 
201  value_type m_constValue; \n
202  }; \n
203  } } \n
204  );
205 
206  template< typename Type >
207  constant_iterator< Type > make_constant_iterator( Type constValue )
208  {
209  constant_iterator< Type > tmp( constValue );
210  return tmp;
211  }
212 
213 }
214 }
215 
217 BOLT_CREATE_CLCODE( bolt::cl::constant_iterator< int >, bolt::cl::deviceConstantIterator );
218 
222 
223 #endif