diff --git a/samples/ffi/http/lib/fake_http.cc b/samples/ffi/http/lib/fake_http.cc index 63b4f1d3853..4420e5e9610 100644 --- a/samples/ffi/http/lib/fake_http.cc +++ b/samples/ffi/http/lib/fake_http.cc @@ -38,11 +38,23 @@ DART_EXPORT void http_get(const char* uri, void (*onResponse)(const char*)) { }).detach(); } -DART_EXPORT void http_serve(void (*onRequest)(const char*)) { - std::thread([onRequest]() { - while (true) { +std::atomic stop_requested = false; +std::thread* server = nullptr; + +DART_EXPORT void http_start_serving(void (*onRequest)(const char*)) { + server = new std::thread([onRequest]() { + while (!stop_requested) { std::this_thread::sleep_for(std::chrono::seconds(1)); onRequest(kExampleRequest); } - }).detach(); + }); } + +DART_EXPORT void http_stop_serving() { + if (server != nullptr) { + stop_requested = true; + server->join(); + delete server; + server = nullptr; + } +} \ No newline at end of file diff --git a/samples/ffi/http/lib/http.dart b/samples/ffi/http/lib/http.dart index 0ce55c2ede4..850d80d056b 100644 --- a/samples/ffi/http/lib/http.dart +++ b/samples/ffi/http/lib/http.dart @@ -39,7 +39,8 @@ Future httpGet(String uri) async { } // Start a HTTP server on a background thread. -void httpServe(void Function(String) onRequest) { +// Returns a function that should be called to stop the server. +Function httpServe(void Function(String) onRequest) { // Create the NativeCallable.listener. void onNativeRequest(Pointer requestPointer) { onRequest(requestPointer.toDartString()); @@ -50,13 +51,12 @@ void httpServe(void Function(String) onRequest) { // Invoke the native function to start the HTTP server. Our example // HTTP library will start a server on a background thread, and pass // any requests it receives to out callback. - nativeHttpServe(callback.nativeFunction); + nativeHttpStartServing(callback.nativeFunction); - // The server will run indefinitely, and the callback needs to stay - // alive for that whole time, so we can't close the callback here. - // But we also don't want the callback to keep the isolate alive - // forever, so we set keepIsolateAlive to false. - callback.keepIsolateAlive = false; + return () { + nativeHttpStopServing(); + callback.close(); + }; } // Load the native functions from a DynamicLibrary. @@ -73,12 +73,21 @@ typedef HttpGetNativeFunction = Void Function( final nativeHttpGet = dylib.lookupFunction('http_get'); -typedef HttpServeFunction = void Function( +typedef HttpStartServingFunction = bool Function( Pointer>); -typedef HttpServeNativeFunction = Void Function( +typedef HttpStartServingNativeFunction = Bool Function( Pointer>); -final nativeHttpServe = dylib - .lookupFunction('http_serve'); +final nativeHttpStartServing = dylib + .lookupFunction( + 'http_start_serving', +); + +typedef HttpStopServingFunction = void Function(); +typedef HttpStopServingNativeFunction = Void Function(); +final nativeHttpStopServing = dylib + .lookupFunction( + 'http_stop_serving', +); Future main() async { print('Sending GET request...'); diff --git a/samples/ffi/http/test/http_test.dart b/samples/ffi/http/test/http_test.dart index 56b092bc8d1..c43ab99ef61 100644 --- a/samples/ffi/http/test/http_test.dart +++ b/samples/ffi/http/test/http_test.dart @@ -16,12 +16,13 @@ Future main() async { test('httpServe', () async { final completer = Completer(); - httpServe((request) { + final callWhenDone = httpServe((request) { if (!completer.isCompleted) { completer.complete(request); } }); final request = await completer.future; expect(request, contains('www.example.com')); + callWhenDone(); }); }