clover: Add property list helpers with a syntax consistent with other API objects.
authorFrancisco Jerez <currojerez@riseup.net>
Tue, 17 Sep 2013 04:13:47 +0000 (21:13 -0700)
committerFrancisco Jerez <currojerez@riseup.net>
Mon, 21 Oct 2013 17:47:03 +0000 (10:47 -0700)
Tested-by: Tom Stellard <thomas.stellard@amd.com>
src/gallium/state_trackers/clover/api/context.cpp
src/gallium/state_trackers/clover/api/util.hpp
src/gallium/state_trackers/clover/core/context.cpp
src/gallium/state_trackers/clover/core/context.hpp
src/gallium/state_trackers/clover/core/property.hpp

index ca05efc2d954b42b290dea0c036ea88d87ad15f4..98bc2141e1165259a27280eab73917f9c1526947 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "api/util.hpp"
 #include "core/context.hpp"
+#include "core/platform.hpp"
 
 using namespace clover;
 
@@ -31,19 +32,21 @@ clCreateContext(const cl_context_properties *d_props, cl_uint num_devs,
                 void (CL_CALLBACK *pfn_notify)(const char *, const void *,
                                                size_t, void *),
                 void *user_data, cl_int *r_errcode) try {
-   auto props = property_map(d_props);
+   auto props = obj<property_list_tag>(d_props);
    auto devs = objs(d_devs, num_devs);
 
    if (!pfn_notify && user_data)
       throw error(CL_INVALID_VALUE);
 
-   for (auto prop : props) {
-      if (prop.first != CL_CONTEXT_PLATFORM)
+   for (auto &prop : props) {
+      if (prop.first == CL_CONTEXT_PLATFORM)
+         obj(prop.second.as<cl_platform_id>());
+      else
          throw error(CL_INVALID_PROPERTY);
    }
 
    ret_error(r_errcode, CL_SUCCESS);
-   return desc(new context(property_vector(props), devs));
+   return desc(new context(props, devs));
 
 } catch (error &e) {
    ret_error(r_errcode, e);
@@ -116,7 +119,7 @@ clGetContextInfo(cl_context d_ctx, cl_context_info param,
       break;
 
    case CL_CONTEXT_PROPERTIES:
-      buf.as_vector<cl_context_properties>() = ctx.props();
+      buf.as_vector<cl_context_properties>() = desc(ctx.props());
       break;
 
    default:
index c8f786e96a2157e3c84e51d6db52b986daf550e0..88f6548f23fa8951844cf4a64daf5c85ad733674 100644 (file)
 #include "util/algorithm.hpp"
 
 namespace clover {
-   ///
-   /// Convert a NULL-terminated property list into an std::map.
-   ///
-   template<typename T>
-   std::map<T, T>
-   property_map(const T *props) {
-      std::map<T, T> m;
-
-      while (props && *props) {
-         T key = *props++;
-         T value = *props++;
-
-         if (m.count(key))
-            throw clover::error(CL_INVALID_PROPERTY);
-
-         m.insert({ key, value });
-      }
-
-      return m;
-   }
-
-   ///
-   /// Convert an std::map into a NULL-terminated property list.
-   ///
-   template<typename T>
-   std::vector<T>
-   property_vector(const std::map<T, T> &m) {
-      std::vector<T> v;
-
-      for (auto &p : m) {
-         v.push_back(p.first);
-         v.push_back(p.second);
-      }
-
-      v.push_back(0);
-      return v;
-   }
-
    ///
    /// Return an error code in \a p if non-zero.
    ///
index 7293f9406f2791aa06049b6cfc53c016dea430e2..7b79f82547eafd3bdcdc139b63ae271602f101f0 100644 (file)
@@ -26,7 +26,7 @@
 
 using namespace clover;
 
-context::context(const std::vector<cl_context_properties> &props,
+context::context(const property_list &props,
                  const ref_vector<device> &devs) :
    devs(map(addresses(), devs)), _props(props) {
 }
@@ -35,3 +35,8 @@ bool
 context::has_device(device &dev) const {
    return std::count(devs.begin(), devs.end(), &dev);
 }
+
+const context::property_list &
+context::props() const {
+   return _props;
+}
index 7ef3db9b9d3c7e647e611e39cc5b2c6306e1be6b..6fda06155ea4480fb3777530e4b306e1eb7378de 100644 (file)
 
 #include "core/object.hpp"
 #include "core/device.hpp"
+#include "core/property.hpp"
 
 namespace clover {
    class context : public ref_counter, public _cl_context {
+   private:
+      typedef clover::property_list<cl_context_properties> property_list;
+
    public:
-      context(const std::vector<cl_context_properties> &props,
-              const ref_vector<device> &devs);
+      context(const property_list &props, const ref_vector<device> &devs);
+
       context(const context &ctx) = delete;
 
       bool has_device(device &dev) const;
 
-      const std::vector<cl_context_properties> &props() const {
-         return _props;
-      }
+      const property_list &
+      props() const;
 
       const std::vector<device *> devs;
 
    private:
-      std::vector<cl_context_properties> _props;
+      property_list _props;
    };
 }
 
index f2e5f2bcd6d15c8b36ddabb1552c1272396abfe9..7f8e17684d945dfc67f91477e38f802facc1014b 100644 (file)
@@ -188,6 +188,74 @@ namespace clover {
          return *this;
       }
    };
+
+   template<typename T>
+   class property_element {
+   public:
+      property_element() : x() {
+      }
+
+      property_element(T x) : x(x) {
+      }
+
+      template<typename S>
+      S
+      as() const {
+         assert(sizeof(S) <= sizeof(T));
+         return reinterpret_cast<S>(x);
+      }
+
+   private:
+      T x;
+   };
+
+   template<typename D>
+   using property_list = std::map<D, property_element<D>>;
+
+   struct property_list_tag;
+
+   ///
+   /// Create a clover::property_list object from a zero-terminated
+   /// CL property list.
+   ///
+   template<typename T, typename D,
+            typename = typename std::enable_if<
+               std::is_same<T, property_list_tag>::value>::type>
+   property_list<D>
+   obj(const D *d_props) {
+      property_list<D> props;
+
+      while (d_props && *d_props) {
+         auto key = *d_props++;
+         auto value = *d_props++;
+
+         if (props.count(key))
+            throw error(CL_INVALID_PROPERTY);
+
+         props.insert({ key, value });
+      }
+
+      return props;
+   }
+
+   ///
+   /// Create a zero-terminated CL property list from a
+   /// clover::property_list object.
+   ///
+   template<typename D>
+   std::vector<D>
+   desc(const property_list<D> &props) {
+      std::vector<D> d_props;
+
+      for (auto &prop : props) {
+         d_props.push_back(prop.first);
+         d_props.push_back(prop.second.template as<D>());
+      }
+
+      d_props.push_back(0);
+
+      return d_props;
+   }
 }
 
 #endif