2323#include < cstdio>
2424#include < cstdlib>
2525#include < optional>
26+ #include < memory>
2627#include < mutex>
2728#include < atomic>
2829#include < thread>
@@ -96,7 +97,7 @@ class HTTPFileSource::Impl {
9697 void checkMultiInfo ();
9798
9899 // Use the dedicated CURL event loop
99- std::unique_ptr <harmony::CURLEventLoop> curlEventLoop;
100+ std::shared_ptr <harmony::CURLEventLoop> curlEventLoop;
100101
101102 // CURL multi handle — now managed by CURLEventLoop
102103 CURLM *multi = nullptr ;
@@ -114,6 +115,10 @@ class HTTPFileSource::Impl {
114115 void setClientOptions (ClientOptions options);
115116 ClientOptions getClientOptions ();
116117
118+ std::shared_ptr<harmony::CURLEventLoop> getEventLoop () const {
119+ return curlEventLoop;
120+ }
121+
117122private:
118123 mutable std::mutex resourceOptionsMutex;
119124 mutable std::mutex clientOptionsMutex;
@@ -133,6 +138,7 @@ class HTTPRequest : public AsyncRequest {
133138 static size_t writeCallback (void *contents, size_t nmemb, size_t size, void *userp);
134139
135140 HTTPFileSource::Impl *context = nullptr ;
141+ std::shared_ptr<harmony::CURLEventLoop> eventLoop;
136142 Resource resource;
137143 FileSource::Callback callback;
138144
@@ -190,7 +196,7 @@ HTTPFileSource::Impl::Impl(const ResourceOptions &resourceOptions_, const Client
190196 mode = harmony::CURLEventLoop::Mode::EventDriven;
191197 }
192198
193- curlEventLoop = std::make_unique <harmony::CURLEventLoop>(mode);
199+ curlEventLoop = std::make_shared <harmony::CURLEventLoop>(mode);
194200 curlEventLoop->start ();
195201
196202 // Obtain the multi handle (owned by CURLEventLoop)
@@ -219,8 +225,8 @@ HTTPFileSource::Impl::~Impl() {
219225 // but ANRDetector helps surface long-running operations.
220226 if (curlEventLoop) {
221227 ANRDetector stopDetector (" curlEventLoop->stop" , 50 , 200 );
222- curlEventLoop-> stop ( );
223- curlEventLoop. reset ();
228+ auto loopRef = std::move (curlEventLoop );
229+ loopRef-> stop ();
224230 }
225231
226232 // Clean up the CURL handle queue (typically quick)
@@ -305,10 +311,18 @@ ClientOptions HTTPFileSource::Impl::getClientOptions() {
305311
306312HTTPRequest::HTTPRequest (HTTPFileSource::Impl *context_, Resource resource_, FileSource::Callback callback_)
307313 : context(context_),
314+ eventLoop (context_ ? context_->getEventLoop () : nullptr),
308315 resource(std::move(resource_)),
309316 callback(std::move(callback_)),
310- handle(context->getHandle ()) {
311-
317+ handle(context_ ? context_->getHandle () : nullptr) {
318+ if (!context) {
319+ throw std::runtime_error (" HTTPFileSource context is null" );
320+ }
321+
322+ if (!handle) {
323+ throw std::runtime_error (" Failed to acquire CURL easy handle" );
324+ }
325+
312326 // Apply URL transforms when a callback is provided.
313327 // Reference Android: platform/android/.../file_source.cpp:122-124
314328 // Reference iOS: platform/darwin/src/MLNOfflineStorage.mm:138-141
@@ -377,8 +391,8 @@ HTTPRequest::HTTPRequest(HTTPFileSource::Impl *context_, Resource resource_, Fil
377391 handleError (curl_easy_setopt (handle, CURLOPT_SHARE , context->share ));
378392
379393 // Start requesting the information using CURLEventLoop
380- if (context-> curlEventLoop ) {
381- bool success = context-> curlEventLoop ->addHandle (handle);
394+ if (eventLoop ) {
395+ bool success = eventLoop ->addHandle (handle);
382396 if (!success) {
383397 Logger::error (" Network" , " ❌ Failed to add handle to CURLEventLoop" );
384398 throw std::runtime_error (" Failed to add handle to CURLEventLoop" );
@@ -407,8 +421,8 @@ HTTPRequest::~HTTPRequest() {
407421 // 3. Clear userp and release resources.
408422
409423 // Step 1: remove the CURL handle from CURLEventLoop (stop new callbacks)
410- if (context && context-> curlEventLoop && handle) {
411- bool success = context-> curlEventLoop ->removeHandle (handle);
424+ if (eventLoop && handle) {
425+ bool success = eventLoop ->removeHandle (handle);
412426
413427 // Step 2: short wait to ensure in-flight callbacks finish
414428 // Note: keep it brief to avoid ANR while still accommodating callbacks
@@ -433,6 +447,8 @@ HTTPRequest::~HTTPRequest() {
433447 curl_slist_free_all (headers);
434448 headers = nullptr ;
435449 }
450+
451+ eventLoop.reset ();
436452}
437453
438454size_t HTTPRequest::writeCallback (void *const contents, const size_t size, const size_t nmemb, void *userp) {
0 commit comments