Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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
  283.