Bolt  1.1
C++ template library with support for OpenCL
counting_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_COUNTING_ITERATOR_H )
19 #define BOLT_CL_COUNTING_ITERATOR_H
20 #include "bolt/cl/bolt.h"
22 #include <boost/iterator/iterator_facade.hpp>
23 
28 namespace bolt {
29 namespace cl {
30 
32  : public fancy_iterator_tag
33  { // identifying tag for random-access iterators
34  };
35 
36  // This represents the host side definition of the counting_iterator template
37  //BOLT_TEMPLATE_FUNCTOR3( counting_iterator, int, float, double,
38  template< typename value_type >
39  class counting_iterator: public boost::iterator_facade< counting_iterator< value_type >, value_type,
40  counting_iterator_tag, value_type, int >
41  {
42  public:
43 
44  typedef typename boost::iterator_facade< counting_iterator< value_type >, value_type,
45  counting_iterator_tag, value_type, int >::difference_type difference_type;
46 
47  struct Payload
48  {
49  value_type m_Value;
50  };
51 
52  // Basic constructor requires a reference to the container and a positional element
53  counting_iterator( value_type init, const control& ctl = control::getDefault( ) ):
54  m_initValue( init ),
55  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 ), &m_initValue );
66  }
67 
68  // This copy constructor allows an iterator to convert into a const_iterator, but not vica versa
69  template< typename OtherType >
70  counting_iterator( const counting_iterator< OtherType >& rhs ): m_devMemory( rhs.m_devMemory ),
71  m_Index( rhs.m_Index ), m_initValue( rhs.m_initValue )
72  {
73  }
74 
75  counting_iterator< value_type >& operator= ( const counting_iterator< value_type >& rhs )
76  {
77  if( this == &rhs )
78  return *this;
79 
80  m_devMemory = rhs.m_devMemory;
81  m_initValue = rhs.m_initValue;
82  m_Index = rhs.m_Index;
83  return *this;
84  }
85 
86  counting_iterator< value_type >& operator+= ( const difference_type & n )
87  {
88  advance( n );
89  return *this;
90  }
91 
92  const counting_iterator< value_type > operator+ ( const difference_type & n ) const
93  {
94  counting_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 counting_iterator< value_type > & getContainer( ) const
105  {
106  return *this;
107  }
108 
109  Payload gpuPayload( ) const
110  {
111  Payload payload = { m_initValue };
112  return payload;
113  }
114 
115  const difference_type gpuPayloadSize( ) const
116  {
117  return sizeof( Payload );
118  }
119 
120 
121  difference_type distance_to( const counting_iterator< value_type >& rhs ) const
122  {
123  //return static_cast< typename iterator_facade::difference_type >( 1 );
124  return rhs.m_Index - m_Index;
125  }
126 
127  // Public member variables
128  difference_type m_Index;
129 
130  private:
131  // Implementation detail of boost.iterator
132  friend class boost::iterator_core_access;
133 
134  // Used for templatized copy constructor and the templatized equal operator
135  template < typename > friend class counting_iterator;
136 
137  // For a counting_iterator, do nothing on an advance
138  void advance(difference_type n )
139  {
140  m_Index += n;
141  }
142 
143  void increment( )
144  {
145  advance( 1 );
146  }
147 
148  void decrement( )
149  {
150  advance( -1 );
151  }
152 
153  template< typename OtherType >
154  bool equal( const counting_iterator< OtherType >& rhs ) const
155  {
156  bool sameIndex = (rhs.m_initValue == m_initValue) && (rhs.m_Index == m_Index);
157 
158  return sameIndex;
159  }
160 
161  typename boost::iterator_facade< counting_iterator< value_type >, value_type,
162  counting_iterator_tag, value_type, int >::reference dereference( ) const
163  {
164  return m_initValue + m_Index;
165  }
166 
167  ::cl::Buffer m_devMemory;
168  value_type m_initValue;
169  };
170  //)
171 
172  // This string represents the device side definition of the counting_iterator template
173  static std::string deviceCountingIterator = STRINGIFY_CODE(
174 
175  namespace bolt { namespace cl { \n
176  template< typename T > \n
177  class counting_iterator \n
178  { \n
179  public: \n
180  typedef int iterator_category; // device code does not understand std:: tags \n
181  typedef T value_type; \n
182  typedef size_t difference_type; \n
183  typedef size_t size_type; \n
184  typedef T* pointer; \n
185  typedef T& reference; \n
186 
187  counting_iterator( value_type init ): m_StartIndex( init ), m_Ptr( 0 ) \n
188  {}; \n
189 
190  void init( global value_type* ptr ) \n
191  { \n
192 
193  //m_Ptr = ptr; \n
194  }; \n
195 
196  value_type operator[]( size_type threadID ) const \n
197  { \n
198  return m_StartIndex + threadID; \n
199  } \n
200 
201  value_type operator*( ) const \n
202  { \n
203  return m_StartIndex + threadID; \n
204  } \n
205 
206  value_type m_StartIndex; \n
207  }; \n
208  } } \n
209  );
210 
211 
212  template< typename Type >
213  counting_iterator< Type > make_counting_iterator( Type constValue )
214  {
215  counting_iterator< Type > tmp( constValue );
216  return tmp;
217  }
218 
219 }
220 }
221 
223 BOLT_CREATE_CLCODE( bolt::cl::counting_iterator< int >, bolt::cl::deviceCountingIterator );
224 
229 
230 #endif