W dniu wtorek, 23 maja 2017 18:09:10 UTC+2 użytkownik Saúl Ibarra Corretgé napisał: > > On Tue, May 23, 2017 at 5:45 PM, Przemysław Sobala > <[email protected] <javascript:>> wrote: > > W dniu wtorek, 23 maja 2017 16:48:46 UTC+2 użytkownik Saúl Ibarra > Corretgé > > napisał: > >> > >> On Tue, May 23, 2017 at 2:14 PM, Przemysław Sobala > >> <[email protected]> wrote: > >> > Hello > >> > I've modified a > >> > https://github.com/curl/curl/blob/master/docs/examples/multi-uv.c > >> > example to > >> > support adding new download requests via multiple threads. > >> > > >> > My design is this: > >> > > >> > 1) In main thread I setup and run uv_loop_t: > >> > loop_mutex.lock(); > >> > uv_run(loop, UV_RUN_DEFAULT); > >> > loop_mutex.unlock(); > >> > but to prevent this loop from quitting in the same thread I'm adding > an > >> > async handle: > >> > uv_async_init(loop, &loop_wakup, NULL); > >> > > >> > 2) A thread can add a new downloading requrst by calling the Add > method: > >> > void FileDownloader::Add(const string url, const string file_path, > >> > done_callback_t done_cb, > >> > error_callback_t error_cb) { > >> > curl_easy_ctx *easy_ctx = new curl_easy_ctx(); > >> > easy_ctx->done_callback = done_cb; > >> > easy_ctx->error_callback = error_cb; > >> > easy_ctx->file = unique_ptr<File>(new File(file_path)); > >> > CURL *handle = curl_easy_init(); > >> > // downloaded data will be written to file > >> > curl_easy_setopt(handle, CURLOPT_WRITEDATA, > >> > easy_ctx->file->InternalHandle()); > >> > // private single downloading context > >> > curl_easy_setopt(handle, CURLOPT_PRIVATE, easy_ctx); > >> > // fail if http response code is >= 400 > >> > curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1); > >> > // follow redirects > >> > curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1); > >> > // whole request timeout [sec] > >> > curl_easy_setopt(handle, CURLOPT_TIMEOUT, req_timeout); > >> > // URL to download > >> > curl_easy_setopt(handle, CURLOPT_URL, url.c_str()); > >> > // disable signal handlers > >> > curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L); > >> > synchronized(curl_handle_mutex) { > >> > curl_multi_add_handle(curl_handle, handle); > >> > } > >> > uv_async_send(&loop_wakup); > >> > LOG(INFO) << "Downloading " << url << " -> " << file_path; > >> > } > >> > as you can see, after adding new curl easy handle I'm waking up the > uv > >> > loop > >> > by calling uv_async_send > >> > > >> > Is this design correct? > >> > > >> > >> I don't think so. With your design other threads will have to wait for > >> the loop to finish running (which will never happen if you have an > >> unref'd async handle) before they can call curl_multi_add_handle, thus > >> making the point of using multiple threads (if that's what you wanted > >> to do) moot. > >> > >> What you can do instead is store the new curl handle in a QUEUE which > >> you protect with a mutex, and wakeup the loop. Then in the async > >> callback call curl_multi_add_handle for each curl handle in the queue. > >> > >> > >> Cheers, > > > > > > Hi Saul > > > > I've though of that. My flow is as follows: > > 1) initialization of uv_loop_t and curl_multi handle > > 2) running mentioned uv_loop_t in separate thread - endlessly by adding > an > > async handle > > 3) "client" threads are calling Add method (it's body is in the first > post) > > > > It seems to do it's job, do you have any comments on that? > > > > I don't see how :-) Given the loop thread takes the lock before > calling uv_run, and uv_run runs endlessly, when will it let go fo the > lock? >
another thread can call uv_stop(loop); uv_async_send(&loop_wakeup); // wait for loop to successfully close loop_mutex.lock(); then it blocks on loop_mutex.lock() and waits for uv_run to exit and release (unlock) the loop_mutex, after that it exists as well. -- You received this message because you are subscribed to the Google Groups "libuv" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/libuv. For more options, visit https://groups.google.com/d/optout.
