summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ForeignExecutorTemplate.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/uniffi_bindgen/src/bindings/python/templates/ForeignExecutorTemplate.py')
-rw-r--r--third_party/rust/uniffi_bindgen/src/bindings/python/templates/ForeignExecutorTemplate.py63
1 files changed, 63 insertions, 0 deletions
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ForeignExecutorTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ForeignExecutorTemplate.py
new file mode 100644
index 0000000000..6a6932fed0
--- /dev/null
+++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ForeignExecutorTemplate.py
@@ -0,0 +1,63 @@
+# FFI code for the ForeignExecutor type
+
+{{ self.add_import("asyncio") }}
+
+_UNIFFI_RUST_TASK_CALLBACK_SUCCESS = 0
+_UNIFFI_RUST_TASK_CALLBACK_CANCELLED = 1
+_UNIFFI_FOREIGN_EXECUTOR_CALLBACK_SUCCESS = 0
+_UNIFFI_FOREIGN_EXECUTOR_CALLBACK_CANCELED = 1
+_UNIFFI_FOREIGN_EXECUTOR_CALLBACK_ERROR = 2
+
+class {{ ffi_converter_name }}:
+ _pointer_manager = _UniffiPointerManager()
+
+ @classmethod
+ def lower(cls, eventloop):
+ if not isinstance(eventloop, asyncio.BaseEventLoop):
+ raise TypeError("_uniffi_executor_callback: Expected EventLoop instance")
+ return cls._pointer_manager.new_pointer(eventloop)
+
+ @classmethod
+ def write(cls, eventloop, buf):
+ buf.write_c_size_t(cls.lower(eventloop))
+
+ @classmethod
+ def read(cls, buf):
+ return cls.lift(buf.read_c_size_t())
+
+ @classmethod
+ def lift(cls, value):
+ return cls._pointer_manager.lookup(value)
+
+@_UNIFFI_FOREIGN_EXECUTOR_CALLBACK_T
+def _uniffi_executor_callback(eventloop_address, delay, task_ptr, task_data):
+ if task_ptr is None:
+ {{ ffi_converter_name }}._pointer_manager.release_pointer(eventloop_address)
+ return _UNIFFI_FOREIGN_EXECUTOR_CALLBACK_SUCCESS
+ else:
+ eventloop = {{ ffi_converter_name }}._pointer_manager.lookup(eventloop_address)
+ if eventloop.is_closed():
+ return _UNIFFI_FOREIGN_EXECUTOR_CALLBACK_CANCELED
+
+ callback = _UNIFFI_RUST_TASK(task_ptr)
+ # FIXME: there's no easy way to get a callback when an eventloop is closed. This means that
+ # if eventloop is called before the `call_soon_threadsafe()` calls are invoked, the call
+ # will never happen and we will probably leak a resource.
+ if delay == 0:
+ # This can be called from any thread, so make sure to use `call_soon_threadsafe'
+ eventloop.call_soon_threadsafe(callback, task_data,
+ _UNIFFI_FOREIGN_EXECUTOR_CALLBACK_SUCCESS)
+ else:
+ # For delayed tasks, we use `call_soon_threadsafe()` + `call_later()` to make the
+ # operation threadsafe
+ eventloop.call_soon_threadsafe(eventloop.call_later, delay / 1000.0, callback,
+ task_data, _UNIFFI_FOREIGN_EXECUTOR_CALLBACK_SUCCESS)
+ return _UNIFFI_FOREIGN_EXECUTOR_CALLBACK_SUCCESS
+
+# Register the callback with the scaffolding
+{%- match ci.ffi_foreign_executor_callback_set() %}
+{%- when Some with (fn) %}
+_UniffiLib.{{ fn.name() }}(_uniffi_executor_callback)
+{%- when None %}
+{#- No foreign executor, we don't set anything #}
+{% endmatch %}