1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
10 
11 #ifndef BOOST_COMPUTE_DETAIL_BUFFER_VALUE_HPP
12 #define BOOST_COMPUTE_DETAIL_BUFFER_VALUE_HPP
13 
14 #include <boost/compute/context.hpp>
15 #include <boost/compute/command_queue.hpp>
16 #include <boost/compute/detail/device_ptr.hpp>
17 #include <boost/compute/detail/read_write_single_value.hpp>
18 
19 namespace boost {
20 namespace compute {
21 namespace detail {
22 
23 template<class T>
24 class buffer_value
25 {
26 public:
27     typedef T value_type;
28 
buffer_value()29     buffer_value()
30     {
31     }
32 
buffer_value(const value_type & value)33     buffer_value(const value_type &value)
34         : m_value(value)
35     {
36     }
37 
38     // creates a reference for the value in buffer at index (in bytes).
buffer_value(const buffer & buffer,size_t index)39     buffer_value(const buffer &buffer, size_t index)
40         : m_buffer(buffer.get(), false),
41           m_index(index)
42     {
43     }
44 
buffer_value(const buffer_value<T> & other)45     buffer_value(const buffer_value<T> &other)
46         : m_buffer(other.m_buffer.get(), false),
47           m_index(other.m_index)
48     {
49     }
50 
~buffer_value()51     ~buffer_value()
52     {
53         // set buffer to null so that its reference count will
54         // not be decremented when its destructor is called
55         m_buffer.get() = 0;
56     }
57 
operator value_type() const58     operator value_type() const
59     {
60         if(m_buffer.get()){
61             const context &context = m_buffer.get_context();
62             const device &device = context.get_device();
63             command_queue queue(context, device);
64 
65             return detail::read_single_value<T>(m_buffer, m_index / sizeof(T), queue);
66         }
67         else {
68             return m_value;
69         }
70     }
71 
operator -() const72     buffer_value<T> operator-() const
73     {
74         return -T(*this);
75     }
76 
operator <(const T & value) const77     bool operator<(const T &value) const
78     {
79         return T(*this) < value;
80     }
81 
operator >(const T & value) const82     bool operator>(const T &value) const
83     {
84         return T(*this) > value;
85     }
86 
operator <=(const T & value) const87     bool operator<=(const T &value) const
88     {
89         return T(*this) <= value;
90     }
91 
operator >=(const T & value) const92     bool operator>=(const T &value) const
93     {
94         return T(*this) <= value;
95     }
96 
operator ==(const T & value) const97     bool operator==(const T &value) const
98     {
99         return T(*this) == value;
100     }
101 
operator ==(const buffer_value<T> & other) const102     bool operator==(const buffer_value<T> &other) const
103     {
104         if(m_buffer.get() != other.m_buffer.get()){
105             return false;
106         }
107 
108         if(m_buffer.get()){
109             return m_index == other.m_index;
110         }
111         else {
112             return m_value == other.m_value;
113         }
114     }
115 
operator !=(const T & value) const116     bool operator!=(const T &value) const
117     {
118         return T(*this) != value;
119     }
120 
operator =(const T & value)121     buffer_value<T>& operator=(const T &value)
122     {
123         if(m_buffer.get()){
124             const context &context = m_buffer.get_context();
125             command_queue queue(context, context.get_device());
126 
127             detail::write_single_value<T>(
128                 value, m_buffer, m_index / sizeof(T), queue
129             ).wait();
130 
131             return *this;
132         }
133         else {
134             m_value = value;
135             return *this;
136         }
137     }
138 
operator =(const buffer_value<T> & value)139     buffer_value<T>& operator=(const buffer_value<T> &value)
140     {
141         return operator=(T(value));
142     }
143 
operator &() const144     detail::device_ptr<T> operator&() const
145     {
146         return detail::device_ptr<T>(m_buffer, m_index);
147     }
148 
operator ++()149     buffer_value<T>& operator++()
150     {
151         if(m_buffer.get()){
152             T value = T(*this);
153             value++;
154             *this = value;
155         }
156         else {
157             m_value++;
158         }
159 
160         return *this;
161     }
162 
operator ++(int)163     buffer_value<T> operator++(int)
164     {
165         buffer_value<T> result(*this);
166         ++(*this);
167         return result;
168     }
169 
170 private:
171     const buffer m_buffer;
172     size_t m_index;
173     value_type m_value;
174 };
175 
176 } // end detail namespace
177 } // end compute namespace
178 } // end boost namespace
179 
180 #endif // BOOST_COMPUTE_DETAIL_BUFFER_VALUE_HPP
181