Skip to content

Commit ae45726

Browse files
authored
Dart: correctly handle callbacks executed from isolate thread outside of its context (#1712)
----- Description of the problem ----- Flutter 3.29 introduced changes in threading model. The Dart code is executed in the main platform thread. Before it was executed by the dedicated UI thread. It is possible to schedule some work via platform-specific API (e.g. Swift: DispatchQueue, Android: Looper) in the way that it will be executed by the main platform thread, but it will be outside of isolate's context. If such work tries to execute Dart's callback from C++ we would see deadlock. ----- Implemented solution ----- The generated code uses NativeCallable.isolateLocal to obtain native function pointers from Dart. Moreover, it stores isolate's thread id and isolate's handle when constructing C++ callable. When we want to execute the callback, then we check if we are in good thread. If we are, but we are not in isolate context, then we manually enter it via Dart DL API. Signed-off-by: Patryk Wrobel <183546751+pwrobeldev@users.noreply.github.com>
1 parent 432fb1d commit ae45726

89 files changed

Lines changed: 5216 additions & 1549 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/functional-tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ jobs:
312312
- name: Install Dart SDK
313313
run: |
314314
DART_RELEASE_CHANNEL=stable
315-
DART_VERSION=2.18.1
315+
DART_VERSION=3.4.4
316316
wget -nv https://storage.googleapis.com/dart-archive/channels/${DART_RELEASE_CHANNEL}/release/${DART_VERSION}/linux_packages/dart_${DART_VERSION}-1_amd64.deb
317317
sudo apt -y install ./dart_${DART_VERSION}-1_amd64.deb
318318
- name: Build and run functional tests
@@ -357,7 +357,7 @@ jobs:
357357
export DART_ROOT=${HOME}/dart_sdk
358358
export DART_BIN=${DART_ROOT}/bin
359359
export PATH=${PATH}:${PWD}/depot_tools:${DART_BIN}
360-
DART_VERSION=2.18.1
360+
DART_VERSION=3.4.4
361361
if [ ! -d "${DART_ROOT}/bin" ]; then
362362
sudo apt install -y python3
363363
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
@@ -428,7 +428,7 @@ jobs:
428428
- name: Install Dart SDK
429429
run: |
430430
DART_RELEASE_CHANNEL=stable
431-
DART_VERSION=2.18.1
431+
DART_VERSION=3.4.4
432432
wget -nv https://storage.googleapis.com/dart-archive/channels/${DART_RELEASE_CHANNEL}/release/${DART_VERSION}/linux_packages/dart_${DART_VERSION}-1_amd64.deb
433433
sudo apt -y install ./dart_${DART_VERSION}-1_amd64.deb
434434
- name: Build and run functional tests

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Gluecodium project Release Notes
22

3+
## Unreleased
4+
### Features
5+
* Dart/Flutter: the generated code is now compatible with Flutter 3.29 and above. When the user invokes the callback created for lambda/interface from the thread that is the main isolate thread, but outside of isolate context then it is correclty executed. Before this release the thread would deadlock. Now the generated code identifies such case and enters the isolate context before invoking the callback.
6+
37
## 13.12.0
48
Release date 2025-03-24
59
### Features

gluecodium/src/main/resources/templates/dart/DartInterface.mustache

Lines changed: 74 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ final _{{resolveName "Ffi"}}ReleaseHandle = __lib.catchArgumentError(() => __lib
100100
void Function(Pointer<Void>)
101101
>('{{libraryName}}_{{resolveName "FfiSnakeCase"}}_release_handle'));
102102
final _{{resolveName "Ffi"}}CreateProxy = __lib.catchArgumentError(() => __lib.nativeLibrary.lookupFunction<
103-
Pointer<Void> Function(Uint64, Int32, Handle{{>ffiFunctionPointers}}),
104-
Pointer<Void> Function(int, int, Object{{>ffiFunctionPointers}})
103+
Pointer<Void> Function(Uint64, Int32, Handle, Pointer{{>ffiFunctionPointers}}),
104+
Pointer<Void> Function(int, int, Object, Pointer{{>ffiFunctionPointers}})
105105
>('{{libraryName}}_{{resolveName "FfiSnakeCase"}}_create_proxy'));
106106
{{#if attributes.equatable}}{{>dart/DartFfiEqualityFunction}}{{/if}}
107107
final _{{resolveName "Ffi"}}GetTypeId = __lib.catchArgumentError(() => __lib.nativeLibrary.lookupFunction<
@@ -173,24 +173,23 @@ class {{resolveName}}$Impl extends __lib.NativeBase implements {{resolveName}} {
173173
}
174174

175175
{{#set parent=this}}{{#each inheritedFunctions functions}}{{#unless isStatic}}
176-
int _{{resolveName parent "Ffi"}}{{resolveName}}Static({{!!
177-
}}Object _obj{{#if parameters}}, {{/if}}{{!!
176+
void _{{resolveName parent "Ffi"}}{{resolveName}}Static({{!!
177+
}}{{resolveName parent}} _obj{{#if parameters}}, {{/if}}{{!!
178178
}}{{#parameters}}{{resolveName typeRef "FfiDartTypes"}} {{resolveName}}{{#if iter.hasNext}}, {{/if}}{{/parameters}}{{!!
179179
}}{{#unless returnType.isVoid}}, Pointer<{{resolveName returnType.typeRef "FfiApiTypes"}}> _result{{/unless}}{{!!
180-
}}{{#if thrownType}}, Pointer<{{resolveName exception.errorType "FfiApiTypes"}}> _error{{/if}}) {
181-
{{#if thrownType}}
182-
bool _errorFlag = false;
183-
{{/if}}{{#unless returnType.isVoid}}
180+
}}{{#if thrownType}}, Pointer<{{resolveName exception.errorType "FfiApiTypes"}}> _error, Pointer<Int8> _errorFlag{{/if}}) {
181+
{{#unless returnType.isVoid}}
184182
{{resolveName returnType.typeRef}}{{#unless returnType.typeRef.isNullable}}?{{/unless}} _resultObject;{{/unless}}
185183
try {
186184
{{#unless returnType.isVoid}}_resultObject = {{/unless}}{{!!
187-
}}(_obj as {{resolveName parent}}).{{resolveName}}({{#parameters}}{{!!
185+
}}_obj.{{resolveName}}({{#parameters}}{{!!
188186
}}{{#set call="FromFfi"}}{{>dart/DartFfiConversionCall}}{{/set}}({{resolveName}}){{#if iter.hasNext}}, {{/if}}{{!!
189187
}}{{/parameters}});{{#unless returnType.isVoid}}
190188
_result.value = {{#returnType}}{{#set call="ToFfi"}}{{>dart/DartFfiConversionCall}}{{/set}}{{/returnType}}(_resultObject);{{/unless}}
191189
{{#if thrownType}}
190+
_errorFlag.value = booleanToFfi(false);
192191
} on {{resolveName exception}} catch(e) {
193-
_errorFlag = true;
192+
_errorFlag.value = booleanToFfi(true);
194193
final _errorObject = e.error;
195194
_error.value = {{#set typeRef=exception.errorType call="ToFfi"}}{{>dart/DartFfiConversionCall}}{{/set}}(_errorObject);
196195
{{/if}}
@@ -199,50 +198,99 @@ int _{{resolveName parent "Ffi"}}{{resolveName}}Static({{!!
199198
{{#resolveName}}{{#set varName=this}}{{>dart/DartFfiReleaseHandle}}{{/set}}{{/resolveName}}
200199
{{/parameters}}
201200
}
202-
return{{#if thrownType}} _errorFlag ? 1 :{{/if}} 0;
203201
}
204202
{{/unless}}{{/each}}
205203

206204
{{#each inheritedProperties properties}}{{#unless isStatic}}
207-
int _{{resolveName parent "Ffi"}}{{resolveName}}GetStatic(Object _obj, Pointer<{{resolveName typeRef "FfiApiTypes"}}> _result) {
205+
void _{{resolveName parent "Ffi"}}{{resolveName}}GetStatic({{resolveName parent}} _obj, Pointer<{{resolveName typeRef "FfiApiTypes"}}> _result) {
208206
_result.value = {{#set call="ToFfi"}}{{>dart/DartFfiConversionCall}}{{/set}}({{!!
209-
}}(_obj as {{resolveName parent}}).{{resolveName}});
210-
return 0;
207+
}}_obj.{{resolveName}});
211208
}
212209
{{#if setter}}
213210

214-
int _{{resolveName parent "Ffi"}}{{resolveName}}SetStatic(Object _obj, {{resolveName typeRef "FfiDartTypes"}} _value) {
211+
void _{{resolveName parent "Ffi"}}{{resolveName}}SetStatic({{resolveName parent}} _obj, {{resolveName typeRef "FfiDartTypes"}} _value) {
215212
try {
216-
(_obj as {{resolveName parent}}).{{resolveName}} =
217-
{{#set call="FromFfi"}}{{>dart/DartFfiConversionCall}}{{/set}}(_value);
213+
_obj.{{resolveName}} = {{#set call="FromFfi"}}{{>dart/DartFfiConversionCall}}{{/set}}(_value);
218214
} finally {
219215
{{#set varName="_value"}}{{>dart/DartFfiReleaseHandle}}{{/set}}
220216
}
221-
return 0;
222217
}
223218
{{/if}}
224219
{{/unless}}{{/each}}{{/set}}
225220

226-
Pointer<Void> {{resolveName "Ffi"}}ToFfi({{resolveName}} value) {
221+
Pointer<Void> {{resolveName "Ffi"}}ToFfi({{resolveName}} __interfaceObj) {
227222
{{#unless isNarrow}}
228-
if (value is __lib.NativeBase) return _{{resolveName "Ffi"}}CopyHandle((value as __lib.NativeBase).handle);
223+
if (__interfaceObj is __lib.NativeBase) return _{{resolveName "Ffi"}}CopyHandle((__interfaceObj as __lib.NativeBase).handle);
229224
{{#eval "descendantInterfaces" fullName}}
230225

231-
final descendantResult = tryDescendantToFfi(value);
226+
final descendantResult = tryDescendantToFfi(__interfaceObj);
232227
if (descendantResult != null) {
233228
return descendantResult;
234229
}
235230
{{/eval}}
236231
{{/unless}}
237232

233+
{{#set parent=this}}{{#each inheritedFunctions functions}}{{#unless isStatic}}
234+
void __{{resolveName}}Caller({{#parameters}}{{resolveName typeRef "FfiDartTypes"}} {{resolveName}}{{#if iter.hasNext}}, {{/if}}{{/parameters}}{{!!
235+
}}{{#unless returnType.isVoid}}{{#if parameters}}, {{/if}}Pointer<{{resolveName returnType.typeRef "FfiApiTypes"}}> _result{{/unless}}{{!!
236+
}}{{#if thrownType}}{{#if parameters}}, {{/if}}{{!!
237+
}}{{#unless parameters}}{{#unless returnType.isVoid}}, {{/unless}}{{/unless}}Pointer<{{resolveName exception.errorType "FfiApiTypes"}}> _error, Pointer<Int8> _errorFlag{{/if}}) { {{!!
238+
}}_{{resolveName parent "Ffi"}}{{resolveName}}Static(__interfaceObj{{#if parameters}}, {{/if}}{{!!
239+
}}{{#parameters}}{{resolveName}}{{#if iter.hasNext}}, {{/if}}{{/parameters}}{{!!
240+
}}{{#unless returnType.isVoid}}, _result{{/unless}}{{!!
241+
}}{{#if thrownType}}, _error, _errorFlag{{/if}}); }
242+
final __{{resolveName}}Callback = NativeCallable<Void Function({{#parameters}}{{resolveName typeRef "FfiApiTypes"}}{{#if iter.hasNext}}, {{/if}}{{/parameters}}{{!!
243+
}}{{#unless returnType.isVoid}}{{#if parameters}}, {{/if}}Pointer<{{resolveName returnType.typeRef "FfiApiTypes"}}>{{/unless}}{{!!
244+
}}{{#if thrownType}}{{#if parameters}}, {{/if}}{{!!
245+
}}{{#unless parameters}}{{#unless returnType.isVoid}}, {{/unless}}{{/unless}}Pointer<{{resolveName exception.errorType "FfiApiTypes"}}>, Pointer<Int8>{{/if}})>.isolateLocal(__{{resolveName}}Caller);
246+
__{{resolveName}}Callback.keepIsolateAlive = false;
247+
248+
{{/unless}}{{/each}}
249+
{{#each inheritedProperties properties}}{{#unless isStatic}}{{#set property=this}}{{!!
250+
}}{{#getter}}
251+
void __{{resolveName parent "Ffi"}}{{resolveName property}}GetCaller(Pointer<{{resolveName property.typeRef "FfiApiTypes"}}> _result) { {{!!
252+
}}_{{resolveName parent "Ffi"}}{{resolveName property}}GetStatic(__interfaceObj, _result); }
253+
final __{{resolveName parent "Ffi"}}{{resolveName property}}GetCallback = NativeCallable<Void Function(Pointer<{{resolveName property.typeRef "FfiApiTypes"}}>)>.isolateLocal(__{{resolveName parent "Ffi"}}{{resolveName property}}GetCaller);
254+
__{{resolveName parent "Ffi"}}{{resolveName property}}GetCallback.keepIsolateAlive = false;
255+
256+
{{/getter}}{{!!
257+
}}{{#setter}}
258+
void __{{resolveName parent "Ffi"}}{{resolveName property}}SetCaller({{resolveName property.typeRef "FfiDartTypes"}} _value) { {{!!
259+
}}_{{resolveName parent "Ffi"}}{{resolveName property}}SetStatic(__interfaceObj, _value); }
260+
final __{{resolveName parent "Ffi"}}{{resolveName property}}SetCallback = NativeCallable<Void Function({{resolveName property.typeRef "FfiApiTypes"}})>.isolateLocal(__{{resolveName parent "Ffi"}}{{resolveName property}}SetCaller);
261+
__{{resolveName parent "Ffi"}}{{resolveName property}}SetCallback.keepIsolateAlive = false;
262+
263+
{{/setter}}
264+
{{/set}}{{/unless}}{{/each}}
265+
{{/set}}
266+
late final NativeCallable<Void Function()> __closeAllCallback;
267+
void __closeAll() {
268+
{{#set parent=this}}{{!!
269+
}}{{#each inheritedFunctions functions}}{{#unless isStatic}}
270+
__{{resolveName}}Callback.close();
271+
{{/unless}}{{/each}}{{!!
272+
}}{{#each inheritedProperties properties}}{{#unless isStatic}}{{#set property=this}}{{!!
273+
}}{{#getter}}
274+
__{{resolveName parent "Ffi"}}{{resolveName property}}GetCallback.close();{{/getter}}{{!!
275+
}}{{#setter}}
276+
__{{resolveName parent "Ffi"}}{{resolveName property}}SetCallback.close();
277+
{{/setter}}{{!!
278+
}}{{/set}}{{/unless}}{{/each}}{{!!
279+
}}{{/set}}
280+
__closeAllCallback.close();
281+
}
282+
__closeAllCallback = NativeCallable<Void Function()>.isolateLocal(__closeAll);
283+
__closeAllCallback.keepIsolateAlive = false;
284+
238285
final result = _{{resolveName "Ffi"}}CreateProxy(
239-
__lib.getObjectToken(value),
286+
__lib.getObjectToken(__interfaceObj),
240287
__lib.LibraryContext.isolateId,
241-
value{{#set parent=this}}{{#each inheritedFunctions functions}}{{#unless isStatic}},
242-
Pointer.fromFunction<{{>ffiApi}}>(_{{resolveName parent "Ffi"}}{{resolveName}}Static, __lib.unknownError){{!!
288+
__interfaceObj,
289+
__closeAllCallback.nativeFunction{{#set parent=this}}{{#each inheritedFunctions functions}}{{#unless isStatic}},
290+
__{{resolveName}}Callback.nativeFunction{{!!
243291
}}{{/unless}}{{/each}}{{#each inheritedProperties properties}}{{#unless isStatic}}{{#set property=this}}{{#getter}},
244-
Pointer.fromFunction<{{>ffiApi}}>(_{{resolveName parent "Ffi"}}{{resolveName property}}GetStatic, __lib.unknownError){{/getter}}{{#setter}},
245-
Pointer.fromFunction<{{>ffiApi}}>(_{{resolveName parent "Ffi"}}{{resolveName property}}SetStatic, __lib.unknownError){{/setter}}{{!!
292+
__{{resolveName parent "Ffi"}}{{resolveName property}}GetCallback.nativeFunction{{/getter}}{{#setter}},
293+
__{{resolveName parent "Ffi"}}{{resolveName property}}SetCallback.nativeFunction{{/setter}}{{!!
246294
}}{{/set}}{{/unless}}{{/each}}{{/set}}
247295
);
248296

gluecodium/src/main/resources/templates/dart/DartLambda.mustache

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ final _{{resolveName "Ffi"}}ReleaseHandle = __lib.catchArgumentError(() => __lib
3838
void Function(Pointer<Void>)
3939
>('{{libraryName}}_{{resolveName "FfiSnakeCase"}}_release_handle'));
4040
final _{{resolveName "Ffi"}}CreateProxy = __lib.catchArgumentError(() => __lib.nativeLibrary.lookupFunction<
41-
Pointer<Void> Function(Uint64, Int32, Handle, Pointer),
42-
Pointer<Void> Function(int, int, Object, Pointer)
41+
Pointer<Void> Function(Uint64, Int32, Handle, Pointer, Pointer),
42+
Pointer<Void> Function(int, int, Object, Pointer, Pointer)
4343
>('{{libraryName}}_{{resolveName "FfiSnakeCase"}}_create_proxy'));
4444

4545
{{#unless disableFinalizableMarker}}{{!!
@@ -57,15 +57,15 @@ final _{{resolveName "Ffi"}}CreateProxy = __lib.catchArgumentError(() => __lib.n
5757
}
5858

5959
{{#set lambda=this}}{{#asFunction}}
60-
int _{{resolveName lambda "Ffi"}}{{resolveName}}Static({{!!
61-
}}Object _obj{{#if parameters}}, {{/if}}{{!!
60+
void _{{resolveName lambda "Ffi"}}{{resolveName}}Static({{!!
61+
}}{{resolveName lambda}} _obj{{#if parameters}}, {{/if}}{{!!
6262
}}{{#parameters}}{{resolveName typeRef "FfiDartTypes"}} {{resolveName}}{{#if iter.hasNext}}, {{/if}}{{/parameters}}{{!!
6363
}}{{#unless returnType.isVoid}}, Pointer<{{resolveName returnType.typeRef "FfiApiTypes"}}> _result{{/unless}}) {
6464
{{#unless returnType.isVoid}}{{resolveName returnType.typeRef}}{{!!
6565
}}{{#unless returnType.typeRef.isNullable}}?{{/unless}} _resultObject;{{/unless}}
6666
try {
6767
{{#unless returnType.isVoid}}_resultObject = {{/unless}}{{!!
68-
}}(_obj as {{resolveName lambda}})({{#parameters}}{{!!
68+
}}_obj({{#parameters}}{{!!
6969
}}{{#set call="FromFfi"}}{{>dart/DartFfiConversionCall}}{{/set}}({{resolveName}}){{#if iter.hasNext}}, {{/if}}{{!!
7070
}}{{/parameters}});{{#unless returnType.isVoid}}
7171
_result.value = {{#returnType}}{{#set call="ToFfi"}}{{>dart/DartFfiConversionCall}}{{/set}}{{/returnType}}(_resultObject);{{/unless}}
@@ -74,17 +74,37 @@ int _{{resolveName lambda "Ffi"}}{{resolveName}}Static({{!!
7474
{{#resolveName}}{{#set varName=this}}{{>dart/DartFfiReleaseHandle}}{{/set}}{{/resolveName}}
7575
{{/parameters}}
7676
}
77-
return 0;
7877
}
7978
{{/asFunction}}{{/set}}
8079

81-
Pointer<Void> {{resolveName "Ffi"}}ToFfi({{resolveName}} value) =>
82-
_{{resolveName "Ffi"}}CreateProxy(
83-
__lib.getObjectToken(value),
80+
Pointer<Void> {{resolveName "Ffi"}}ToFfi({{resolveName}} __lambdaObj) {
81+
{{#set lambda=this}}{{#asFunction}}
82+
void __lambdaCaller({{#parameters}}{{resolveName typeRef "FfiDartTypes"}} {{resolveName}}{{#if iter.hasNext}}, {{/if}}{{/parameters}}{{!!
83+
}}{{#unless returnType.isVoid}}{{#if parameters}}, {{/if}}Pointer<{{resolveName returnType.typeRef "FfiApiTypes"}}> _result{{/unless}}) { {{!!
84+
}}_{{resolveName lambda "Ffi"}}{{resolveName}}Static(__lambdaObj{{#if parameters}}, {{/if}}{{!!
85+
}}{{#parameters}}{{resolveName}}{{#if iter.hasNext}}, {{/if}}{{/parameters}}{{!!
86+
}}{{#unless returnType.isVoid}}, _result{{/unless}}); }
87+
final __lambdaCallback = NativeCallable<Void Function({{#parameters}}{{resolveName typeRef "FfiApiTypes"}}{{#if iter.hasNext}}, {{/if}}{{/parameters}}{{!!
88+
}}{{#unless returnType.isVoid}}{{#if parameters}}, {{/if}}Pointer<{{resolveName returnType.typeRef "FfiApiTypes"}}>{{/unless}})>.isolateLocal(__lambdaCaller);
89+
{{/asFunction}}{{/set}}
90+
__lambdaCallback.keepIsolateAlive = false;
91+
92+
late final NativeCallable<Void Function()> __closeAllCallback;
93+
void __closeAll() {
94+
__lambdaCallback.close();
95+
__closeAllCallback.close();
96+
}
97+
__closeAllCallback = NativeCallable<Void Function()>.isolateLocal(__closeAll);
98+
__closeAllCallback.keepIsolateAlive = false;
99+
100+
return _{{resolveName "Ffi"}}CreateProxy(
101+
__lib.getObjectToken(__lambdaObj),
84102
__lib.LibraryContext.isolateId,
85-
value,{{#set lambda=this}}{{#asFunction}}
86-
Pointer.fromFunction<{{>ffiApi}}>(_{{resolveName lambda "Ffi"}}{{resolveName}}Static, __lib.unknownError){{/asFunction}}{{/set}}
103+
__lambdaObj,
104+
__closeAllCallback.nativeFunction,
105+
__lambdaCallback.nativeFunction
87106
);
107+
}
88108

89109
{{#unless isAsyncLambda}}
90110
{{resolveName}} {{resolveName "Ffi"}}FromFfi(Pointer<Void> handle) {

gluecodium/src/main/resources/templates/ffi/FfiHeader.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ _GLUECODIUM_FFI_EXPORT void {{libraryName}}_{{resolveName}}_release_handle(FfiOp
5353

5454
{{#each interfaces lambdas asyncHelpers.lambdas}}
5555
_GLUECODIUM_FFI_EXPORT FfiOpaqueHandle {{libraryName}}_{{resolveName}}_create_proxy({{!!
56-
}}uint64_t token, int32_t isolate_id, Dart_Handle dart_handle{{!!
56+
}}uint64_t token, int32_t isolate_id, Dart_Handle dart_handle, FfiOpaqueHandle close_callbacks{{!!
5757
}}{{#each inheritedFunctions functions}}{{#unless isStatic}}{{#ifPredicate "shouldRetain"}}{{!!
5858
}}, FfiOpaqueHandle f{{iter.position}}{{/ifPredicate}}{{/unless}}{{/each}}{{!!
5959
}}{{#each inheritedProperties properties}}{{#unless isStatic}}{{#ifPredicate "shouldRetain"}}, FfiOpaqueHandle p{{iter.position}}g{{!!

gluecodium/src/main/resources/templates/ffi/FfiImplementation.mustache

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
{{/includes}}
3535
#include <memory>
3636
#include <new>
37+
{{#if interfaces lambdas asyncHelpers.lambdas logic="or"}}
38+
#include <thread>
39+
{{/if}}
3740

3841
{{#interfaces}}
3942
{{>ffi/FfiProxyDeclaration}}
@@ -98,7 +101,7 @@ void
98101

99102
{{#interfaces}}
100103
FfiOpaqueHandle
101-
{{libraryName}}_{{resolveName}}_create_proxy(uint64_t token, int32_t isolate_id, Dart_Handle dart_handle{{!!
104+
{{libraryName}}_{{resolveName}}_create_proxy(uint64_t token, int32_t isolate_id, Dart_Handle dart_handle, FfiOpaqueHandle close_callbacks{{!!
102105
}}{{#each inheritedFunctions functions}}{{#unless isStatic}}{{#ifPredicate "shouldRetain"}}{{!!
103106
}}, FfiOpaqueHandle f{{iter.position}}{{/ifPredicate}}{{/unless}}{{/each}}{{!!
104107
}}{{#each inheritedProperties properties}}{{#unless isStatic}}{{#ifPredicate "shouldRetain"}}, FfiOpaqueHandle p{{iter.position}}g{{!!
@@ -111,10 +114,11 @@ FfiOpaqueHandle
111114
{{#unless this.attributes.nocache}}
112115
if (cached_proxy) {
113116
proxy_ptr = new (std::nothrow) std::shared_ptr<{{resolveName}}_Proxy>(cached_proxy);
117+
(*reinterpret_cast<void (*)()>(close_callbacks))();
114118
} else {
115119
{{/unless}}
116120
proxy_ptr = new (std::nothrow) std::shared_ptr<{{resolveName}}_Proxy>(
117-
new (std::nothrow) {{resolveName}}_Proxy(token, isolate_id, dart_handle{{!!
121+
new (std::nothrow) {{resolveName}}_Proxy(token, isolate_id, dart_handle, close_callbacks{{!!
118122
}}{{#each inheritedFunctions functions}}{{#unless isStatic}}{{#ifPredicate "shouldRetain"}}{{!!
119123
}}, f{{iter.position}}{{/ifPredicate}}{{/unless}}{{/each}}{{!!
120124
}}{{#each inheritedProperties properties}}{{#unless isStatic}}{{#ifPredicate "shouldRetain"}}, p{{iter.position}}g{{!!
@@ -132,14 +136,16 @@ FfiOpaqueHandle
132136

133137
{{+ffiLambdaProxy}}
134138
FfiOpaqueHandle
135-
{{libraryName}}_{{resolveName}}_create_proxy(uint64_t token, int32_t isolate_id, Dart_Handle dart_handle, FfiOpaqueHandle f0) {
139+
{{libraryName}}_{{resolveName}}_create_proxy(uint64_t token, int32_t isolate_id, Dart_Handle dart_handle, FfiOpaqueHandle close_callbacks, FfiOpaqueHandle f0) {
136140
{{#if this.attributes.nocache}}
137141
auto cached_proxy = std::make_shared<{{resolveName}}_Proxy>(token, isolate_id, dart_handle, f0);
138142
{{/if}}{{#unless this.attributes.nocache}}
139143
auto cached_proxy = {{>ffi/FfiInternal}}::get_cached_proxy<{{resolveName}}_Proxy>(token, isolate_id, "{{resolveName}}");
140144
if (!cached_proxy) {
141-
cached_proxy = std::make_shared<{{resolveName}}_Proxy>(token, isolate_id, dart_handle, f0);
145+
cached_proxy = std::make_shared<{{resolveName}}_Proxy>(token, isolate_id, dart_handle, close_callbacks, f0);
142146
{{>ffi/FfiInternal}}::cache_proxy(token, isolate_id, "{{resolveName}}", cached_proxy);
147+
} else {
148+
(*reinterpret_cast<void (*)()>(close_callbacks))();
143149
}
144150
{{/unless}}
145151

0 commit comments

Comments
 (0)