Passing messages between multiple threads of LIBUV

Source: Internet
Author: User

Official web-based example Http://nikhilm.github.io/uvbook/threads.html#inter-thread-communication, Chinese understanding behind

Inter-thread Communication

Sometimes want various threads to actually send each other messages while they is running. For example might is running some long duration task in a separate thread (perhaps using uv_queue_work) but W Ant to notify progress to the main thread. This was a simple example of having a download manager informing the user of the status of running downloads.

Progress/main.c

1 2 3 4 5 6 7 8 9101112131415
uv_loop_t*Loop;uv_async_tAsync;IntMain(){Loop=Uv_default_loop();uv_work_tReq;IntSize=10240;Req.Data= (void*) & Size; uv_async_init (loop& asyncprint_progress); uv_queue_work (loop& reqfake_downloadafter ); return uv_run (loop uv_run_default);                /span>                

The async thread communication works on loops so although no thread can be the message sender, only threads with LIBUV loops can be receivers (or rather the loop is the receiver). LIBUV would invoke the callback (print_progress) with the Async watcher whenever it receives a message.

Warning

It is important to realize this message send isAsync, the callback May is invoked immediately afterUv_async_sendWas called in another thread, or it could be invoked after some time. LIBUV also combine multiple calls toUv_async_sendand invoke your callback only once. The only guarantee, LIBUV makes Is–the callback function is calledAt least onceAfter the call toUv_async_send. If you have no pending calls toUv_async_sendThe callback won ' t be called. If you make both or more calls, and libuv hasn ' t had a chance to run the callback yet, it MayInvoke your callbackOnly onceFor the multiple invocations ofUv_async_send. Your callback'll never is called twice for just one event.

Progress/main.c

1 2 3 4 5 6 7 8 91011121314
voidFake_download(uv_work_t*Req){IntSize=*((Int*)Req-Data);IntDownloaded=0;DoublePercentage;While(Downloaded<Size){Percentage=Downloaded*100.0/Size; async. Data =  (void*)  &percentage; uv_async_send (&asyncsleep (1downloaded +=  (200+ random ()) %1000//can only download Max 1000bytes/sec, //but at least a 200; }}             /span>                

In the download function we modify the progress indicator and queues the message for delivery with Uv_async_send. Remember: uv_async_send is also non-blocking and would return immediately.

Progress/main.c

1234
 void print_progress (uv_async_t *handleint status /*unused*/) {double percentage = * ((double*) span class= "n" >handle->data); fprintf (stderr "downloaded%.2f %%\n "percentage); }   

The callback is a standard LIBUV pattern, extracting the data from the watcher.

Finally It is important to remember to the watcher.

Progress/main.c

 1234 
 void after (uv_work_t * reqint status) {fprintf (stderr  "Download complete\n" ); uv_close ((uv_handle_t*) &asyncnull); }  

After this example, which showed the abuse of the data field, Bnoordhuis pointed out that using the data field is not thread safe, and uv_async_send () are actually only meant to wake up the event loop. Use a mutex or rwlock to ensure accesses is performed in the right order.

This also has the Chinese version of the translation, can be searched online.

The last mentioned uv_async_t.data is not thread-safe, and I understand the following:

A message loop loop (Uv_loop_t object) is opened in the main thread, and an asynchronous Message listener async (uv_async_t object) is registered for the loop, and other threads can send messages to the main thread via async. The practice is to save the data under Async, then send async to Loop,loop asynchronously to get async, and then get the data from async and handle it. I want to say that there is only one async object, there is no copy in the process of delivery, so from the sending message to the message is fetched and processed, during which the Async object is thread insecure, and should be coupled with a synchronization mechanism to ensure that the entire period of the Async object to serve only one other thread. But what if the asynchronous messaging mechanism provided by LIBUV is not used when synchronizing? Our multi-threaded threads will also encounter bottlenecks here.

There are two ways to solve my problem:

1. Each time the other thread sends a message to the main thread, it creates a new async object and temporarily registers it with the loop; when the loop gets the async object, it finishes, logs off and deletes the async object

2. Register multiple Async objects at the same time and save them in the queue. When other threads send a message to the main thread, the mutex obtains one of the async objects, and when the loop finishes processing the Async object, it is mutually exclusive and inserted back into the queue. Although this also has synchronous operation, its synchronization period is greatly reduced, and the degree of thread parallelism is improved.

Passing messages between multiple threads of LIBUV

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.