From 7c6233df78f342d83f59810b1d220129b1335434 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 27 May 2014 08:42:32 -0400 Subject: [PATCH] event callback directly using object pointer --- pyopencl/_cffi.py | 9 ++++-- pyopencl/c_wrapper/wrap_cl_core.h | 7 ++--- pyopencl/cffi_cl.py | 3 +- src/c_wrapper/error.h | 5 ++-- src/c_wrapper/pyhelper.cpp | 37 ++++++++---------------- src/c_wrapper/pyhelper.h | 47 +++++++++++++++++++++++++++++++ src/c_wrapper/utils.h | 3 -- src/c_wrapper/wrap_cl.cpp | 14 ++++----- 8 files changed, 78 insertions(+), 47 deletions(-) create mode 100644 src/c_wrapper/pyhelper.h diff --git a/pyopencl/_cffi.py b/pyopencl/_cffi.py index 97e2db24..8033ae65 100644 --- a/pyopencl/_cffi.py +++ b/pyopencl/_cffi.py @@ -164,8 +164,7 @@ if _lib.have_gl(): _ffi.cdef(_get_wrap_header("wrap_cl_gl_core.h")) import gc -_gc_collect = _ffi.callback('int(void)')(gc.collect) -_lib.set_gc(_gc_collect) +_py_gc = _ffi.callback('int(void)')(gc.collect) _pyrefs = {} @_ffi.callback('void(void*)') @@ -179,4 +178,8 @@ def _py_deref(handle): def _py_ref(handle): _pyrefs[handle] = handle -_lib.set_ref_funcs(_py_ref, _py_deref) +@_ffi.callback('void(void*, cl_int)') +def _py_call(handle, status): + _ffi.from_handle(handle)(status) + +_lib.set_py_funcs(_py_gc, _py_ref, _py_deref, _py_call) diff --git a/pyopencl/c_wrapper/wrap_cl_core.h b/pyopencl/c_wrapper/wrap_cl_core.h index 0480d0c8..1a211fe5 100644 --- a/pyopencl/c_wrapper/wrap_cl_core.h +++ b/pyopencl/c_wrapper/wrap_cl_core.h @@ -42,8 +42,8 @@ typedef struct { int get_cl_version(); void free_pointer(void*); void free_pointer_array(void**, uint32_t size); -void set_gc(int (*func)()); -void set_ref_funcs(void (*ref)(void*), void (*deref)(void*)); +void set_py_funcs(int (*_gc)(), void (*_ref)(void*), void (*_deref)(void*), + void (*_call)(void*, cl_int)); int have_gl(); unsigned bitlog2(unsigned long v); @@ -114,8 +114,7 @@ error *image__get_image_info(clobj_t image, cl_image_info param, error *event__get_profiling_info(clobj_t event, cl_profiling_info param, generic_info *out); error *event__wait(clobj_t event); -error *event__set_callback(clobj_t _evt, cl_int type, void (*cb)(cl_int), - void *pyobj); +error *event__set_callback(clobj_t _evt, cl_int type, void *pyobj); error *wait_for_events(const clobj_t *_wait_for, uint32_t num_wait_for); // Nanny Event void *nanny_event__get_ward(clobj_t evt); diff --git a/pyopencl/cffi_cl.py b/pyopencl/cffi_cl.py index 72dc0ab4..35be93f2 100644 --- a/pyopencl/cffi_cl.py +++ b/pyopencl/cffi_cl.py @@ -688,10 +688,9 @@ class Event(_Common): _handle_error(_lib.event__wait(self.ptr)) def set_callback(self, _type, cb, *args, **kwargs): - @_ffi.callback('void(cl_int)') def _func(status): cb(status, *args, **kwargs) - _handle_error(_lib.event__set_callback(self.ptr, _type, _func, + _handle_error(_lib.event__set_callback(self.ptr, _type, _ffi.new_handle(_func))) def wait_for_events(wait_for): diff --git a/src/c_wrapper/error.h b/src/c_wrapper/error.h index f1f3c3ff..d1fa7f62 100644 --- a/src/c_wrapper/error.h +++ b/src/c_wrapper/error.h @@ -1,4 +1,5 @@ #include "wrap_cl.h" +#include "pyhelper.h" #include #include #include @@ -11,8 +12,6 @@ namespace pyopencl { -extern int (*python_gc)(); - #ifdef PYOPENCL_TRACE template @@ -165,7 +164,7 @@ retry_mem_error(std::function func) try { return func(); } catch (clerror &e) { - if (!e.is_out_of_memory() || !python_gc()) { + if (!e.is_out_of_memory() || !py::gc()) { throw; } } diff --git a/src/c_wrapper/pyhelper.cpp b/src/c_wrapper/pyhelper.cpp index d76f7ac6..ca18c96a 100644 --- a/src/c_wrapper/pyhelper.cpp +++ b/src/c_wrapper/pyhelper.cpp @@ -1,35 +1,22 @@ -#include "utils.h" -#include "error.h" -#include +#include "pyhelper.h" namespace pyopencl { -static int -dummy_python_gc() -{ - return 0; +namespace py { +WrapFunc gc; +WrapFunc ref; +WrapFunc deref; +WrapFunc call; } -static void -dummy_python_ref_func(void*) -{ -} - -int (*python_gc)() = dummy_python_gc; -void (*python_deref)(void*) = dummy_python_ref_func; -void (*python_ref)(void*) = dummy_python_ref_func; - -} - -void -set_gc(int (*func)()) -{ - pyopencl::python_gc = func ? func : pyopencl::dummy_python_gc; } void -set_ref_funcs(void (*ref)(void*), void (*deref)(void*)) +set_py_funcs(int (*_gc)(), void (*_ref)(void*), void (*_deref)(void*), + void (*_call)(void*, cl_int)) { - pyopencl::python_ref = ref ? ref : pyopencl::dummy_python_ref_func; - pyopencl::python_deref = deref ? deref : pyopencl::dummy_python_ref_func; + pyopencl::py::gc = _gc; + pyopencl::py::ref = _ref; + pyopencl::py::deref = _deref; + pyopencl::py::call = _call; } diff --git a/src/c_wrapper/pyhelper.h b/src/c_wrapper/pyhelper.h new file mode 100644 index 00000000..de5daf5e --- /dev/null +++ b/src/c_wrapper/pyhelper.h @@ -0,0 +1,47 @@ +#ifndef __PYOPENCL_PYHELPER_H +#define __PYOPENCL_PYHELPER_H + +#include "wrap_cl.h" +#include + +namespace pyopencl { + +template +class WrapFunc; + +template +class WrapFunc { + typedef Ret (*_FuncType)(Args...); + _FuncType m_func; + static inline _FuncType + check_func(_FuncType f) + { + return f ? f : ([] (Args...) {return Ret();}); + } +public: + WrapFunc(_FuncType func=NULL) + : m_func(check_func(func)) + {} + Ret + operator()(Args... args) + { + return m_func(std::forward(args)...); + } + WrapFunc& + operator=(_FuncType func) + { + m_func = check_func(func); + return *this; + } +}; + +namespace py { +extern WrapFunc gc; +extern WrapFunc ref; +extern WrapFunc deref; +extern WrapFunc call; +} + +} + +#endif diff --git a/src/c_wrapper/utils.h b/src/c_wrapper/utils.h index 6114e69a..57bdad79 100644 --- a/src/c_wrapper/utils.h +++ b/src/c_wrapper/utils.h @@ -307,9 +307,6 @@ get_int_info(cl_int (*func)(ArgTypes...), const char *name, // }}} -extern void (*python_ref)(void*); -extern void (*python_deref)(void*); - } #endif diff --git a/src/c_wrapper/wrap_cl.cpp b/src/c_wrapper/wrap_cl.cpp index f38f8a52..59d029e5 100644 --- a/src/c_wrapper/wrap_cl.cpp +++ b/src/c_wrapper/wrap_cl.cpp @@ -1,6 +1,7 @@ #include "error.h" #include "utils.h" #include "async.h" +#include "pyhelper.h" #include @@ -808,7 +809,7 @@ public: : event(evt, retain), m_ward(ward) { if (ward) { - python_ref(ward); + py::ref(ward); } } ~nanny_event() @@ -828,7 +829,7 @@ public: // No lock needed because multiple release is safe here. void *ward = m_ward; m_ward = NULL; - python_deref(ward); + py::deref(ward); } }; static inline event* @@ -2312,17 +2313,16 @@ event__wait(clobj_t evt) } #if PYOPENCL_CL_VERSION >= 0x1010 -// TODO directly use pyobj to do callback error* -event__set_callback(clobj_t _evt, cl_int type, void (*cb)(cl_int), void *pyobj) +event__set_callback(clobj_t _evt, cl_int type, void *pyobj) { auto evt = static_cast(_evt); return c_handle_error([&] { evt->set_callback(type, [=] (cl_int status) { - cb(status); - python_deref(pyobj); + py::call(pyobj, status); + py::deref(pyobj); }); - python_ref(pyobj); + py::ref(pyobj); }); } #endif -- GitLab