#include "api/util.hpp"
#include "core/context.hpp"
+#include "core/platform.hpp"
using namespace clover;
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);
break;
case CL_CONTEXT_PROPERTIES:
- buf.as_vector<cl_context_properties>() = ctx.props();
+ buf.as_vector<cl_context_properties>() = desc(ctx.props());
break;
default:
#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.
///
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) {
}
context::has_device(device &dev) const {
return std::count(devs.begin(), devs.end(), &dev);
}
+
+const context::property_list &
+context::props() const {
+ return _props;
+}
#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;
};
}
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