From b98251638cf265e369512565777357dba66c5fcb Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Mon, 10 Jul 2017 09:57:35 -0500 Subject: [PATCH] Add a flag indicating whether the type string in generic_info needs to be freed, and use constructor function for generic_info (Fixes #186 on Github) --- pyopencl/cffi_cl.py | 6 +++- src/c_wrapper/clhelper.h | 61 +++++++++++++++++------------------- src/c_wrapper/context.cpp | 24 +++++++------- src/c_wrapper/device.cpp | 7 +---- src/c_wrapper/program.cpp | 11 ++++--- src/c_wrapper/wrap_cl_core.h | 3 +- 6 files changed, 54 insertions(+), 58 deletions(-) diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py index 2851b02c..62f9edbf 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -144,6 +144,10 @@ class _CArray(object): def _generic_info_to_python(info): type_ = _ffi_pystr(info.type) + + if info.free_type: + _lib.free_pointer(info.type) + value = _ffi.cast(type_, info.value) if info.opaque_class != _lib.CLASS_NONE: @@ -200,7 +204,7 @@ def _generic_info_to_python(info): ret = list(value) else: ret = value[0] - if info.dontfree == 0: + if info.free_value: _lib.free_pointer(info.value) return ret diff --git a/src/c_wrapper/clhelper.h b/src/c_wrapper/clhelper.h index c88c0051..d0aff85c 100644 --- a/src/c_wrapper/clhelper.h +++ b/src/c_wrapper/clhelper.h @@ -86,17 +86,27 @@ get_vec_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name, #define pyopencl_get_vec_info(type, what, ...) \ get_vec_info(clGet##what##Info, "clGet" #what "Info", __VA_ARGS__) +inline generic_info make_generic_info(class_t opaque_class, const char *type, bool free_type, void *value, bool free_value) +{ + generic_info result; + result.opaque_class = opaque_class; + result.type = type; + result.free_type = free_type; + result.value = value; + result.free_value = free_value; + return result; +} + template PYOPENCL_USE_RESULT static PYOPENCL_INLINE generic_info convert_array_info(const char *tname, pyopencl_buf &buf) { - generic_info info; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; - info.type = _copy_str(std::string(tname) + "[" + - tostring(buf.len()) + "]"); - info.value = buf.release(); - return info; + return make_generic_info( + CLASS_NONE, + _copy_str(std::string(tname) + "[" + tostring(buf.len()) + "]"), + true, + buf.release(), + true); } template @@ -116,12 +126,12 @@ template PYOPENCL_USE_RESULT static PYOPENCL_INLINE generic_info convert_opaque_array_info(T &&buf) { - generic_info info; - info.dontfree = 0; - info.opaque_class = CLObj::class_id; - info.type = _copy_str(std::string("void*[") + tostring(buf.len()) + "]"); - info.value = buf_to_base(std::forward(buf)).release(); - return info; + return make_generic_info( + CLObj::class_id, + _copy_str(std::string("void*[") + tostring(buf.len()) + "]"), + true, + buf_to_base(std::forward(buf)).release(), + true); } #define pyopencl_get_opaque_array_info(cls, what, ...) \ convert_opaque_array_info( \ @@ -134,16 +144,13 @@ get_opaque_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name, { typename CLObj::cl_type param_value; call_guarded(func, name, args..., size_arg(param_value), nullptr); - generic_info info; - info.dontfree = 0; - info.opaque_class = CLObj::class_id; - info.type = "void *"; + void *value; if (param_value) { - info.value = (void*)(new CLObj(param_value, /*retain*/ true)); + value = (void*)(new CLObj(param_value, /*retain*/ true)); } else { - info.value = nullptr; + value = nullptr; } - return info; + return make_generic_info(CLObj::class_id, "void *", false, value, true); } #define pyopencl_get_opaque_info(clobj, what, ...) \ get_opaque_info(clGet##what##Info, \ @@ -158,12 +165,7 @@ get_str_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name, call_guarded(func, name, args..., 0, nullptr, buf_arg(size)); pyopencl_buf param_value(size); call_guarded(func, name, args..., param_value, buf_arg(size)); - generic_info info; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; - info.type = "char*"; - info.value = (void*)param_value.release(); - return info; + return make_generic_info(CLASS_NONE, "char*", false, (void*)param_value.release(), true); } #define pyopencl_get_str_info(what, ...) \ get_str_info(clGet##what##Info, "clGet" #what "Info", __VA_ARGS__) @@ -175,12 +177,7 @@ get_int_info(cl_int (CL_API_CALL *func)(ArgTypes...), const char *name, { T value; call_guarded(func, name, args..., size_arg(value), nullptr); - generic_info info; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; - info.type = tpname; - info.value = cl_memdup(&value); - return info; + return make_generic_info(CLASS_NONE, tpname, false, cl_memdup(&value), true); } #define pyopencl_get_int_info(type, what, ...) \ get_int_info(clGet##what##Info, "clGet" #what "Info", \ diff --git a/src/c_wrapper/context.cpp b/src/c_wrapper/context.cpp index f2478fd7..0fe48554 100644 --- a/src/c_wrapper/context.cpp +++ b/src/c_wrapper/context.cpp @@ -56,15 +56,12 @@ context::get_info(cl_uint param_name) const if (key == 0) break; cl_context_properties value = result[i * 2 + 1]; - generic_info &info = py_result[i]; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; switch (key) { case CL_CONTEXT_PLATFORM: - info.opaque_class = CLASS_PLATFORM; - info.type = "void *"; - info.value = new platform( - reinterpret_cast(value)); + py_result[i] = make_generic_info( + CLASS_PLATFORM, + "void *", false, + new platform(reinterpret_cast(value)), true); break; #if defined(PYOPENCL_GL_SHARING_VERSION) && (PYOPENCL_GL_SHARING_VERSION >= 1) @@ -77,12 +74,13 @@ context::get_info(cl_uint param_name) const case CL_WGL_HDC_KHR: case CL_CGL_SHAREGROUP_KHR: #endif - info.type = "intptr_t *"; - info.value = (void*)value; - // we do not own this object - info.dontfree = 1; - break; - + py_result[i] = make_generic_info( + CLASS_NONE, + "intptr_t *", false, + (void*)value, + // we do not own this object + false); + break; #endif default: throw clerror("Context.get_info", CL_INVALID_VALUE, diff --git a/src/c_wrapper/device.cpp b/src/c_wrapper/device.cpp index 7bc7fd5a..16edaf34 100644 --- a/src/c_wrapper/device.cpp +++ b/src/c_wrapper/device.cpp @@ -37,12 +37,7 @@ get_device_topology_amd(ArgTypes&&... args) cl_device_topology_amd value; const char * fname = "clGetDeviceInfo"; call_guarded(clGetDeviceInfo, fname, args..., size_arg(value), nullptr); - generic_info info; - info.dontfree = 0; - info.opaque_class = CLASS_NONE; - info.type = tpname; - info.value = cl_memdup(&value); - return info; + return make_generic_info(CLASS_NONE, tpname, false, cl_memdup(&value), true); } #define pyopencl_get_device_topology_amd(...) get_device_topology_amd(__VA_ARGS__) diff --git a/src/c_wrapper/program.cpp b/src/c_wrapper/program.cpp index d50d9680..a0535c06 100644 --- a/src/c_wrapper/program.cpp +++ b/src/c_wrapper/program.cpp @@ -54,11 +54,12 @@ program::get_info(cl_uint param) const } pyopencl_buf gis(sizes.len()); for (size_t i = 0;i < sizes.len();i++) { - gis[i].value = result_ptrs[i]; - gis[i].dontfree = 0; - gis[i].opaque_class = CLASS_NONE; - gis[i].type = _copy_str(std::string("char[") + - tostring(sizes[i]) + "]"); + gis[i] = make_generic_info( + CLASS_NONE, + _copy_str(std::string("char[") + tostring(sizes[i]) + "]"), + true, + result_ptrs[i], + true); } return pyopencl_convert_array_info(generic_info, gis); } diff --git a/src/c_wrapper/wrap_cl_core.h b/src/c_wrapper/wrap_cl_core.h index 746c1b9d..184cd001 100644 --- a/src/c_wrapper/wrap_cl_core.h +++ b/src/c_wrapper/wrap_cl_core.h @@ -43,8 +43,9 @@ typedef enum { typedef struct { class_t opaque_class; const char *type; + bool free_type; void *value; - int dontfree; + bool free_value; } generic_info; // }}} -- GitLab