2009-08-26 26 views
9

Để triển khai lớp new_handler cụ thể, tôi đã xem ví dụ sau trong sách "hiệu quả C++". Điều này có vẻ vấn đề trong môi trường đa luồng, Câu hỏi của tôi là làm thế nào để đạt được new_handler lớp cụ thể trong môi trường đa luồng?sử dụng set_new_handler lớp cụ thể

void * X::operator new(size_t size) 
{ 
    new_handler globalHandler =    // install X's 
    std::set_new_handler(currentHandler); // handler 
    void *memory; 
    try {          // attempt 
     memory = ::operator new(size);   // allocation 
    } 
    catch (std::bad_alloc&) {     // restore 
     std::set_new_handler(globalHandler);  // handler; 
     throw;         // propagate 
    }           // exception 
    std::set_new_handler(globalHandler);  // restore 
               // handler 
    return memory; 
} 

Trả lời

4

Bạn nói đúng. Đây có lẽ không phải là chủ đề an toàn. Bạn có thể muốn xem xét một cách tiếp cận khác như sử dụng các nothrow version of new thay vì:

void* X::operator new(std::size_t sz) { 
    void *p; 
    while ((p = ::operator new(sz, std::nothrow) == NULL) { 
    X::new_handler(); 
    } 
    return p; 
} 

Điều này sẽ gây ra xử lý đẳng cấp cụ thể của bạn được gọi là bất cứ khi nào cấp phát bộ nhớ bị lỗi. Tôi sẽ không làm điều này cho đến khi bạn thực sự hiểu tất cả các cơn đau đầu xung quanh quá tải operator new. Đặc biệt, hãy đọc hai bài viết về phần của Herb Sutter Để mới, Perchance để ném, Part 1Part 2. Điều thú vị là, anh ta nói để tránh phiên bản nothrow ... hmmm.

0

C++ chưa biết chủ đề là gì. Bạn sẽ phải chuyển sang thư viện chuẩn/thư viện chuẩn/thư viện hệ điều hành/thư viện chuẩn của C++ để xác định một cách an toàn cho thread để thực hiện điều này, hoặc nếu nó thậm chí có thể. Tôi sẽ đề nghị rằng trình xử lý mới có lẽ sẽ giống nhau trên ứng dụng. Nó không phải là một cơ chế rất linh hoạt, có lẽ nhu cầu của bạn sẽ được phục vụ tốt hơn với một người cấp phát hoặc có lẽ là một nhà máy (chức năng)? Bạn đang muốn làm gì bên trong trình xử lý mới tùy chỉnh?

0

Có thể bạn đang xem xét sai cách. Tôi không nghĩ có cách nào để hạn chế toàn bộ ứng dụng từ cấp phát bộ nhớ (vì phần lớn phân bổ bộ nhớ có thể nằm ngoài mã của bạn), vì vậy cách tốt nhất để làm điều đó là kiểm soát những gì bạn có thể - tức là việc thực hiện của người xử lý.

Thiết lập trình xử lý để gọi một thể hiện của lớp "OutOfMemoryHandler" (gọi đó là những gì bạn sẽ) ở đầu chương trình và có hành vi mặc định để gọi trình xử lý hiện có. Khi bạn muốn thêm xử lý lớp cụ thể, hãy thêm một hành vi vào OutOfMemoryHandler của bạn bằng cách sử dụng các kỹ thuật C++ yêu thích của bạn cho hành vi động.

Giải pháp này sẽ hoạt động tốt trong môi trường đơn luồng, nhưng sẽ không thành công trong môi trường nhiều luồng. Để làm cho nó hoạt động trong môi trường đa luồng, bạn cần phải có người gọi thông báo cho đối tượng xử lý rằng nó đang làm việc trong một chủ đề cụ thể; chuyển thread-id với class sẽ là một cách hay để làm điều này. Nếu trình xử lý được gọi, thì nó sẽ kiểm tra thread-id và xác định hành vi thực hiện dựa trên lớp được liên kết. Khi cuộc gọi mới() kết thúc, chỉ cần hủy đăng ký chuỗi-id để đảm bảo hành vi mặc định chính xác (giống như bạn đã thực hiện khi đặt lại trình xử lý mặc định).

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