1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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 %}
|