Add delivery executor in callbackinfo structs
Bug: b/374925431
Change-Id: I51954dd020d3ccb5345aa438ea1ef04fc2061583
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/262655
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Nikita Gupta <nikigupta@google.com>
Reviewed-by: Jim Blackler <jimblackler@google.com>
diff --git a/generator/templates/art/JNIClasses.cpp b/generator/templates/art/JNIClasses.cpp
index c92f237..e4a6612 100644
--- a/generator/templates/art/JNIClasses.cpp
+++ b/generator/templates/art/JNIClasses.cpp
@@ -36,6 +36,9 @@
//* Time of lookups measured on Pixel 6 at 1.7ms.
{% for entity in has_kotlin_classes %}
{{ entity.name.camelCase() }} = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("{{ jni_name(entity) }}")));
+ {%if entity.category == 'callback function' %}
+ {{ entity.name.camelCase() }}Runnable = reinterpret_cast<jclass>(env->NewGlobalRef(env->FindClass("{{ jni_name(entity) }}Runnable")));
+ {%endif %}
{% endfor %}
}
diff --git a/generator/templates/art/JNIClasses.h b/generator/templates/art/JNIClasses.h
index 915320f..762b06a 100644
--- a/generator/templates/art/JNIClasses.h
+++ b/generator/templates/art/JNIClasses.h
@@ -38,8 +38,10 @@
static JNIClasses* getInstance(JNIEnv* env);
{% for entity in has_kotlin_classes %}
jclass {{ entity.name.camelCase() }};
+ {%if entity.category == 'callback function' %}
+ jclass {{ entity.name.camelCase() }}Runnable;
+ {%endif %}
{% endfor %}
-
private:
JNIClasses(JNIEnv *env);
};
diff --git a/generator/templates/art/api_kotlin_function_pointer.kt b/generator/templates/art/api_kotlin_function_pointer.kt
index 143ef58..ff6a3b3 100644
--- a/generator/templates/art/api_kotlin_function_pointer.kt
+++ b/generator/templates/art/api_kotlin_function_pointer.kt
@@ -37,3 +37,21 @@
{{ as_varName(arg.name) }}: {{ kotlin_declaration(arg) }},{{ ' ' }}
{%- endfor -%});
}
+
+{% set args_list = kotlin_record_members(function_pointer.arguments) | list %}
+
+internal class {{ function_pointer.name.CamelCase() }}Runnable(
+private val callback: {{ function_pointer.name.CamelCase() }},
+{% for arg in args_list %}
+ private val {{ as_varName(arg.name) }}: {{ kotlin_declaration(arg) }}{{ ','
+ if not loop.last }}
+{% endfor %}
+) : Runnable {
+ override fun run() {
+ callback.{{ callbackName }}(
+ {%- for arg in args_list -%}
+ {{ as_varName(arg.name) }}{{ ', ' if not loop.last }}
+ {%- endfor -%}
+ )
+ }
+}
diff --git a/generator/templates/art/api_kotlin_structure.kt b/generator/templates/art/api_kotlin_structure.kt
index 7b277e2..374e6e6 100644
--- a/generator/templates/art/api_kotlin_structure.kt
+++ b/generator/templates/art/api_kotlin_structure.kt
@@ -27,8 +27,17 @@
package {{ kotlin_package }}
{% from 'art/api_kotlin_types.kt' import kotlin_definition with context %}
+{% for member in kotlin_record_members(structure.members) %}
+ import java.util.concurrent.Executor
+ import java.util.concurrent.ForkJoinPool
+ {% break %}
+{% endfor %}
+
public class {{ structure.name.CamelCase() }}(
{% for member in kotlin_record_members(structure.members) %}
+ {% if member.type.category in ['callback function']%}
+ public var executor: Executor? = ForkJoinPool.commonPool(),
+ {% endif %}
{# We supply a getter that is excluded from name mangling to allow Inline Value Classed
enums/bitmasks to be accessible as integers from the JVM adapter layer. #}
{% if member.type.category in ['bitmask', 'enum'] %}
diff --git a/generator/templates/art/kotlin_record_conversion.cpp b/generator/templates/art/kotlin_record_conversion.cpp
index 8302bf2..012b9b9 100644
--- a/generator/templates/art/kotlin_record_conversion.cpp
+++ b/generator/templates/art/kotlin_record_conversion.cpp
@@ -37,6 +37,9 @@
{% else %}
{{ arg_to_jni_type(member) }} {{ as_varName(member.name) }};
{% endif %}
+ {% if as_varName(member.name) == 'callback' %}
+ jobject executor;
+ {% endif %}
{% endfor%}
};
{% endmacro %}
@@ -50,6 +53,9 @@
{% for member in kotlin_record_members(members) %}
{
auto& in = inStruct.{{member.name.camelCase()}};
+ {% if as_varName(member.name) == 'callback' %}
+ auto& in_executor = inStruct.executor;
+ {% endif %}
auto& out = outStruct->{{member.name.camelCase()}};
{% if member.constant_length == 1 %}
{% if member.type.category == 'structure' %}
@@ -170,21 +176,30 @@
//* Get the client (Kotlin) callback so we can call it.
{% set callbackName = 'on' + member.type.name.chunks[:-1] | map('title') | join %}
- jmethodID callbackMethod = env->GetMethodID(
- classes->{{ member.type.name.camelCase() }}, "{{ callbackName }}", "(
+ jclass executorClass = env->FindClass("java/util/concurrent/Executor");
+ jmethodID executeMethodID = env->GetMethodID(executorClass,
+ "execute",
+ "(Ljava/lang/Runnable;)V");
+ jmethodID methodId = env->GetMethodID(
+ classes->{{ member.type.name.camelCase() }}Runnable,
+ "<init>", "(L{{ jni_name(member.type) }};
{%- for callbackArg in kotlin_record_members(member.type.arguments) -%}
{{- jni_signature(callbackArg) -}}
{%- endfor %})V");
- //* Call the callback with all converted parameters.
- env->CallVoidMethod(userData1->callback, callbackMethod
- {%- for callbackArg in kotlin_record_members(member.type.arguments) %}
- {{- ', ' }}_{{ callbackArg.name.camelCase() }}
- {%- endfor %});
+ jobject runnable =
+ env->NewObject(classes->{{ member.type.name.camelCase() }}Runnable,
+ methodId,
+ userData1->callback
+ {%- for callbackArg in kotlin_record_members(member.type.arguments) %}
+ {{- ', ' }}_{{ callbackArg.name.camelCase() }}
+ {%- endfor %});
+
+ env->CallVoidMethod(userData1->executor, executeMethodID, runnable);
};
//* TODO(b/330293719): free associated resources.
outStruct->{{ userdata }} = new UserData(
- {.callback = env->NewGlobalRef(in), .jvm = c->jvm});
+ {.callback = env->NewGlobalRef(in), .executor = inStruct.executor, .jvm = c->jvm});
{% else %}
{{ unreachable_code() }}
diff --git a/generator/templates/art/structures.cpp b/generator/templates/art/structures.cpp
index 5ef2dfd..0373164 100644
--- a/generator/templates/art/structures.cpp
+++ b/generator/templates/art/structures.cpp
@@ -170,6 +170,10 @@
CallGetter(env, getter, obj, &kotlinRecord.{{as_varName(member.name)}});
}
{% endfor %}
+ {% if structure.category == 'callback info' %}
+ jmethodID getter = env->GetMethodID(clz, "getExecutor", "()Ljava/util/concurrent/Executor;");
+ CallGetter(env, getter, obj, &kotlinRecord.executor);
+ {% endif %}
//* Fill all struct members from the Kotlin record.
ConvertInternal(c, kotlinRecord, converted);
diff --git a/generator/templates/art/structures.h b/generator/templates/art/structures.h
index b7fcce4..ae8fe10 100644
--- a/generator/templates/art/structures.h
+++ b/generator/templates/art/structures.h
@@ -33,6 +33,7 @@
struct UserData {
jobject callback;
+ jobject executor;
JavaVM *jvm;
};