2012-12-12 40 views
13

Tôi đã tạo một chuỗi mới dành riêng cho vòng lặp chạy libuv. Chức năng chủ đề trông giống như sau:Chủ đề libuv có an toàn không?

void thread_function() 
{ 
    uv_loop_t *loop = uv_loop_new(); 
    uv_ref(loop); 
    uv_run(loop); 
} 

Tăng truy cập ref giữ cho luồng còn sống và trong trạng thái xử lý sự kiện libuv. Tôi hy vọng sẽ có thể gây ra vòng lặp chạy để kết thúc, do đó gây ra các thread để thoát, bằng cách thực hiện uv_unref trên chủ đề chính.

Tuy nhiên, khi kiểm tra mã nguồn uv_ref tôi không thấy bất kỳ đảm bảo nào truy cập vào biến số lượt truy cập tham chiếu sẽ được đồng bộ trong khi truy cập đồng thời. Ngoài ra, tôi không thấy bất kỳ lệnh gọi lợi nhuận nào để từ bỏ quyền kiểm soát đối với hệ điều hành trong vòng lặp chạy, nghĩa là chương trình sẽ không hợp tác tốt với các quy trình khác.

Điều này khiến tôi tin rằng tôi không sử dụng libuv đúng cách. Nếu ai đó có thể giải thích những gì tôi đang làm sai, điều đó thật tuyệt!

Trả lời

30

Không, libuv không phải là chủ đề an toàn theo cách này. Bạn nên sử dụng uv_async để báo hiệu vòng lặp thoát. uv_async là cơ sở an toàn thread duy nhất mà libuv có.

Nó sẽ giống như thế này:

uv_async_t exit_handle; 

void exit_async_cb(uv_async_t* handle, int status) { 
    /* After closing the async handle, it will no longer keep the loop alive. */ 
    uv_close((uv_handle_t*) &exit_handle, NULL); 
} 

void thread_function() { 
    uv_loop_t *loop = uv_loop_new(); 
    /* The existence of the async handle will keep the loop alive. */ 
    uv_async_init(loop, &exit_handle, exit_async_cb); 
    uv_run(loop); 
} 

Bây giờ từ thread khác mà bạn có thể báo hiệu vòng lặp này để thoát bằng cách gọi

uv_async_send(&exit_handle); 

Bạn cần phải chăm sóc để không gọi uv_async_send() trước chủ đề khác đã hoàn thành thiết lập vòng lặp và xử lý uv_async. Phiên bản gần đây của libuv bao gồm các nguyên thủy đồng bộ hóa uv_barrier mà bạn có thể sử dụng; nhưng phiên bản libuv mà tàu với Node.js 0.8 không hỗ trợ điều này được nêu ra, vì vậy bạn có thể cần phải sử dụng các tiện ích pthread để thực hiện công việc này.

Một lưu ý phụ, dường như bạn đang gọi uv_refuv_unref với tham chiếu vòng lặp làm đối số. Trong các phiên bản libuv gần đây, điều này đã thay đổi, bây giờ bạn được yêu cầu là uv_refuv_unref một xử lý cụ thể. Xem uv.h để biết chi tiết.

Các vấn đề liên quan