clover: implements clSetContextDestructorCallback

Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Francisco Jerez <currojerez@riseup.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7468>
diff --git a/src/gallium/frontends/clover/api/context.cpp b/src/gallium/frontends/clover/api/context.cpp
index c0cd2d3..1618756 100644
--- a/src/gallium/frontends/clover/api/context.cpp
+++ b/src/gallium/frontends/clover/api/context.cpp
@@ -142,3 +142,21 @@
 } catch (error &e) {
    return e.get();
 }
+
+CLOVER_API cl_int
+clSetContextDestructorCallback(cl_context d_ctx,
+                               void (CL_CALLBACK *pfn_notify)(cl_context, void *),
+                               void *user_data) try {
+   CLOVER_NOT_SUPPORTED_UNTIL("3.0");
+   auto &ctx = obj(d_ctx);
+
+   if (!pfn_notify)
+      return CL_INVALID_VALUE;
+
+   ctx.destroy_notify([=]{ pfn_notify(d_ctx, user_data); });
+
+   return CL_SUCCESS;
+
+} catch (error &e) {
+   return e.get();
+}
diff --git a/src/gallium/frontends/clover/api/dispatch.cpp b/src/gallium/frontends/clover/api/dispatch.cpp
index 8c0d7af..2c6c6e8 100644
--- a/src/gallium/frontends/clover/api/dispatch.cpp
+++ b/src/gallium/frontends/clover/api/dispatch.cpp
@@ -172,6 +172,6 @@
       NULL, // clSetProgramSpecializationConstant
       NULL, // clCreateBufferWithProperties
       NULL, // clCreateImageWithProperties
-      NULL, // clSetContextDestructorCallback
+      clSetContextDestructorCallback
    };
 }
diff --git a/src/gallium/frontends/clover/core/context.cpp b/src/gallium/frontends/clover/core/context.cpp
index c3e2082..e5255e7 100644
--- a/src/gallium/frontends/clover/core/context.cpp
+++ b/src/gallium/frontends/clover/core/context.cpp
@@ -30,6 +30,13 @@
    notify(notify), props(props), devs(devs) {
 }
 
+context::~context() {
+   while (_destroy_notify.size()) {
+      _destroy_notify.top()();
+      _destroy_notify.pop();
+   }
+}
+
 bool
 context::operator==(const context &ctx) const {
    return this == &ctx;
@@ -40,6 +47,11 @@
    return this != &ctx;
 }
 
+void
+context::destroy_notify(std::function<void ()> f) {
+   _destroy_notify.push(f);
+}
+
 const context::property_list &
 context::properties() const {
    return props;
diff --git a/src/gallium/frontends/clover/core/context.hpp b/src/gallium/frontends/clover/core/context.hpp
index 7b22cca..bbde48b 100644
--- a/src/gallium/frontends/clover/core/context.hpp
+++ b/src/gallium/frontends/clover/core/context.hpp
@@ -23,6 +23,8 @@
 #ifndef CLOVER_CORE_CONTEXT_HPP
 #define CLOVER_CORE_CONTEXT_HPP
 
+#include <stack>
+
 #include "core/object.hpp"
 #include "core/device.hpp"
 #include "core/property.hpp"
@@ -36,6 +38,8 @@
       typedef clover::property_list<cl_context_properties> property_list;
 
    public:
+      ~context();
+
       typedef std::function<void (const char *)> notify_action;
 
       context(const property_list &props, const ref_vector<device> &devs,
@@ -50,6 +54,8 @@
       bool
       operator!=(const context &ctx) const;
 
+      void destroy_notify(std::function<void ()> f);
+
       const property_list &
       properties() const;
 
@@ -61,6 +67,7 @@
    private:
       property_list props;
       const std::vector<intrusive_ref<device>> devs;
+      std::stack<std::function<void ()>> _destroy_notify;
    };
 }