2 // Copyright 2012 Francisco Jerez
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:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
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.
23 #ifndef _CORE_BASE_HPP_
24 #define _CORE_BASE_HPP_
36 /// Main namespace of the CL state tracker.
40 /// Class that represents an error that can be converted to an
41 /// OpenCL status code.
43 class error : public std::runtime_error {
45 error(cl_int code, std::string what = "") :
46 std::runtime_error(what), code(code) {
58 /// Base class for objects that support reference counting.
62 ref_counter() : _ref_count(1) {}
64 unsigned ref_count() {
73 return (--_ref_count) == 0;
77 std::atomic<unsigned> _ref_count;
81 /// Intrusive smart pointer for objects that implement the
82 /// clover::ref_counter interface.
87 ref_ptr(T *q = NULL) : p(NULL) {
91 ref_ptr(const ref_ptr<T> &ref) : p(NULL) {
99 void reset(T *q = NULL) {
102 if (p && p->release())
107 ref_ptr &operator=(const ref_ptr &ref) {
112 T *operator*() const {
116 T *operator->() const {
120 operator bool() const {
129 /// Transfer the caller's ownership of a reference-counted object
130 /// to a clover::ref_ptr smart pointer.
135 ref_ptr<T> ref { p };
140 template<typename T, typename S, int N>
141 struct _iter_helper {
142 template<typename F, typename Its, typename... Args>
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...);
150 template<typename T, typename S>
151 struct _iter_helper<T, S, 0> {
152 template<typename F, typename Its, typename... Args>
154 step(F op, S state, Its its, Args... args) {
155 return op(state, *(std::get<0>(its)++), args...);
162 struct _iter_helper<T, _empty, 0> {
163 template<typename F, typename Its, typename... Args>
165 step(F op, _empty state, Its its, Args... args) {
166 return op(*(std::get<0>(its)++), args...);
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...)
180 /// Iterate \a op on the result of zipping all the specified
181 /// iterators together.
183 /// Similar to std::for_each, but it accepts functions of an
184 /// arbitrary number of arguments.
186 template<typename F, typename It0, typename... Its>
188 for_each(F op, It0 it0, It0 end0, Its... its) {
190 _iter_helper<void, _empty, sizeof...(Its)>::step(
191 op, {}, std::tie(it0, its...));
197 /// Iterate \a op on the result of zipping all the specified
198 /// iterators together, storing return values in a new container.
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.
204 template<typename F, typename It0, typename... Its,
205 typename C = std::vector<
206 typename _result_helper<F, It0, Its...>::type>>
208 map(F op, It0 it0, It0 end0, Its... its) {
213 _iter_helper<typename C::value_type, _empty, sizeof...(Its)>
214 ::step(op, {}, std::tie(it0, its...)));
220 /// Reduce the result of zipping all the specified iterators
221 /// together, using iterative application of \a op from left to
224 /// Similar to std::accumulate, but it accepts functions of an
225 /// arbitrary number of arguments.
227 template<typename F, typename T, typename It0, typename... Its>
229 fold(F op, T a, It0 it0, It0 end0, Its... its) {
231 a = _iter_helper<T, T, sizeof...(Its)>::step(
232 op, a, std::tie(it0, its...));
238 /// Iterate \a op on the result of zipping the specified iterators
239 /// together, checking if any of the evaluations returns \a true.
241 /// Similar to std::any_of, but it accepts functions of an
242 /// arbitrary number of arguments.
244 template<typename F, typename It0, typename... Its>
246 any_of(F op, It0 it0, It0 end0, Its... its) {
248 if (_iter_helper<bool, _empty, sizeof...(Its)>::step(
249 op, {}, std::tie(it0, its...)))
255 template<typename T, typename S>
257 keys(const std::pair<T, S> &ent) {
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;
269 template<typename T, typename S>
271 values(const std::pair<T, S> &ent) {