clover: Replace a bunch of double underscores with single underscores.
[mesa.git] / src / gallium / state_trackers / clover / core / base.hpp
1 //
2 // Copyright 2012 Francisco Jerez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22
23 #ifndef _CORE_BASE_HPP_
24 #define _CORE_BASE_HPP_
25
26 #include <stdexcept>
27 #include <atomic>
28 #include <cassert>
29 #include <tuple>
30 #include <vector>
31 #include <functional>
32
33 #include "CL/cl.h"
34
35 ///
36 /// Main namespace of the CL state tracker.
37 ///
38 namespace clover {
39 ///
40 /// Class that represents an error that can be converted to an
41 /// OpenCL status code.
42 ///
43 class error : public std::runtime_error {
44 public:
45 error(cl_int code, std::string what = "") :
46 std::runtime_error(what), code(code) {
47 }
48
49 cl_int get() const {
50 return code;
51 }
52
53 protected:
54 cl_int code;
55 };
56
57 ///
58 /// Base class for objects that support reference counting.
59 ///
60 class ref_counter {
61 public:
62 ref_counter() : _ref_count(1) {}
63
64 unsigned ref_count() {
65 return _ref_count;
66 }
67
68 void retain() {
69 _ref_count++;
70 }
71
72 bool release() {
73 return (--_ref_count) == 0;
74 }
75
76 private:
77 std::atomic<unsigned> _ref_count;
78 };
79
80 ///
81 /// Intrusive smart pointer for objects that implement the
82 /// clover::ref_counter interface.
83 ///
84 template<typename T>
85 class ref_ptr {
86 public:
87 ref_ptr(T *q = NULL) : p(NULL) {
88 reset(q);
89 }
90
91 ref_ptr(const ref_ptr<T> &ref) : p(NULL) {
92 reset(ref.p);
93 }
94
95 ~ref_ptr() {
96 reset(NULL);
97 }
98
99 void reset(T *q = NULL) {
100 if (q)
101 q->retain();
102 if (p && p->release())
103 delete p;
104 p = q;
105 }
106
107 ref_ptr &operator=(const ref_ptr &ref) {
108 reset(ref.p);
109 return *this;
110 }
111
112 T *operator*() const {
113 return p;
114 }
115
116 T *operator->() const {
117 return p;
118 }
119
120 operator bool() const {
121 return p;
122 }
123
124 private:
125 T *p;
126 };
127
128 ///
129 /// Transfer the caller's ownership of a reference-counted object
130 /// to a clover::ref_ptr smart pointer.
131 ///
132 template<typename T>
133 inline ref_ptr<T>
134 transfer(T *p) {
135 ref_ptr<T> ref { p };
136 p->release();
137 return ref;
138 }
139
140 template<typename T, typename S, int N>
141 struct _iter_helper {
142 template<typename F, typename Its, typename... Args>
143 static T
144 step(F op, S state, Its its, Args... args) {
145 return _iter_helper<T, S, N - 1>::step(
146 op, state, its, *(std::get<N>(its)++), args...);
147 }
148 };
149
150 template<typename T, typename S>
151 struct _iter_helper<T, S, 0> {
152 template<typename F, typename Its, typename... Args>
153 static T
154 step(F op, S state, Its its, Args... args) {
155 return op(state, *(std::get<0>(its)++), args...);
156 }
157 };
158
159 struct _empty {};
160
161 template<typename T>
162 struct _iter_helper<T, _empty, 0> {
163 template<typename F, typename Its, typename... Args>
164 static T
165 step(F op, _empty state, Its its, Args... args) {
166 return op(*(std::get<0>(its)++), args...);
167 }
168 };
169
170 template<typename F, typename... Its>
171 struct _result_helper {
172 typedef typename std::remove_const<
173 typename std::result_of<
174 F (typename std::iterator_traits<Its>::value_type...)
175 >::type
176 >::type type;
177 };
178
179 ///
180 /// Iterate \a op on the result of zipping all the specified
181 /// iterators together.
182 ///
183 /// Similar to std::for_each, but it accepts functions of an
184 /// arbitrary number of arguments.
185 ///
186 template<typename F, typename It0, typename... Its>
187 F
188 for_each(F op, It0 it0, It0 end0, Its... its) {
189 while (it0 != end0)
190 _iter_helper<void, _empty, sizeof...(Its)>::step(
191 op, {}, std::tie(it0, its...));
192
193 return op;
194 }
195
196 ///
197 /// Iterate \a op on the result of zipping all the specified
198 /// iterators together, storing return values in a new container.
199 ///
200 /// Similar to std::transform, but it accepts functions of an
201 /// arbitrary number of arguments and it doesn't have to be
202 /// provided with an output iterator.
203 ///
204 template<typename F, typename It0, typename... Its,
205 typename C = std::vector<
206 typename _result_helper<F, It0, Its...>::type>>
207 C
208 map(F op, It0 it0, It0 end0, Its... its) {
209 C c;
210
211 while (it0 != end0)
212 c.push_back(
213 _iter_helper<typename C::value_type, _empty, sizeof...(Its)>
214 ::step(op, {}, std::tie(it0, its...)));
215
216 return c;
217 }
218
219 ///
220 /// Reduce the result of zipping all the specified iterators
221 /// together, using iterative application of \a op from left to
222 /// right.
223 ///
224 /// Similar to std::accumulate, but it accepts functions of an
225 /// arbitrary number of arguments.
226 ///
227 template<typename F, typename T, typename It0, typename... Its>
228 T
229 fold(F op, T a, It0 it0, It0 end0, Its... its) {
230 while (it0 != end0)
231 a = _iter_helper<T, T, sizeof...(Its)>::step(
232 op, a, std::tie(it0, its...));
233
234 return a;
235 }
236
237 ///
238 /// Iterate \a op on the result of zipping the specified iterators
239 /// together, checking if any of the evaluations returns \a true.
240 ///
241 /// Similar to std::any_of, but it accepts functions of an
242 /// arbitrary number of arguments.
243 ///
244 template<typename F, typename It0, typename... Its>
245 bool
246 any_of(F op, It0 it0, It0 end0, Its... its) {
247 while (it0 != end0)
248 if (_iter_helper<bool, _empty, sizeof...(Its)>::step(
249 op, {}, std::tie(it0, its...)))
250 return true;
251
252 return false;
253 }
254
255 template<typename T, typename S>
256 T
257 keys(const std::pair<T, S> &ent) {
258 return ent.first;
259 }
260
261 template<typename T, typename S>
262 std::function<bool (const std::pair<T, S> &)>
263 key_equals(const T &x) {
264 return [=](const std::pair<T, S> &ent) {
265 return ent.first == x;
266 };
267 }
268
269 template<typename T, typename S>
270 S
271 values(const std::pair<T, S> &ent) {
272 return ent.second;
273 }
274
275 template<typename T>
276 bool
277 is_zero(T x) {
278 return x == 0;
279 }
280 }
281
282 #endif