2010-07-01 22 views
6

Tôi có một wrapper nhỏ mà tập trung những gì liên quan đến chủ đề:"phương pháp ảo tinh khiết gọi là" khi thực hiện một sự thúc đẩy :: chủ đề wrapper giao diện

class Thread { 
protected: 
    boost::thread *m_thread; 

    virtual void work() = 0; 

    void do_work() { 
     work(); 
    } 

public: 
    Thread() : m_thread(NULL) {} 
    virtual ~Thread() { 
     catch_up(); 
     delete m_thread; 
    } 

    inline void catch_up() { 
     if(m_thread != NULL) { 
      m_thread->join(); 
     } 
    } 

    void run() { 
     m_thread = new boost::thread(boost::bind(&Thread::do_work, boost::ref(*this))); 
    } 
}; 

Khi tôi thực hiện nó, nói như sau:

class A : public Thread { 
    void work() {} 
}; 

tại:

A a; a.run(); 

tôi có một chấm dứt thời gian chạy với một khá "phương pháp ảo tinh khiết gọi là" displ ayed. Tôi nghĩ rằng đó là tăng :: đối số ràng buộc, nhưng tôi không biết làm thế nào để nói "Sử dụng ảo thực hiện tinh khiết" ...

Cảm ơn trước.

Kính trọng,

Mister Mystère

Trả lời

6

vụ tai nạn của bạn chỉ xảy ra khi chương trình của bạn thoát ra ngay lập tức: nó gọi hạng A của destructor mà thúc và gọi destructor Chủ đề của trước thread mới bắt đầu đã có một cơ hội để được sắp xếp. Sau đó, thread gọi hàm ảo của bạn, nhưng lớp A không còn tồn tại nữa, do đó, nó gọi là do_work() của Thread, gọi là công việc ảo thuần túy(). Dưới đây là chương trình của bạn với kết quả đầu ra phụ:

run() started 
run() ended 
~A() started 
~A() ended 
~Thread() started 
catch_up() started 
do_work() started 
pure virtual method called 

Standard-khôn ngoan, tôi nghĩ rằng đây là hành vi không xác định vì cuộc đời của đối tượng đã kết thúc (gọi destructor bắt đầu) khi một tham chiếu đến nó (boost::ref(*this)) được sử dụng để gọi do_work () từ chuỗi.

Giải pháp: để cho chủ đề của bạn thực hiện trước khi bạn hủy đối tượng của bạn:

A a; a.run(); 
a.catch_up(); 

Hoặc, như tài liệu boost.thread nói, "the user of Boost.Thread must ensure that the referred-to object outlives the newly-created thread of execution."

+0

Vâng, đó là đơn giản ... Cảm ơn, bạn đã làm cho nó rõ ràng. Nhưng bây giờ tôi có một vấn đề lớn hơn (ngẫu nhiên booleans rõ ràng ...), và tôi nghĩ rằng nó sẽ được wayyy khó khăn hơn để gỡ lỗi. Tôi chỉ không nên sử dụng "joker" của tôi ở đây cho điều đó, nếu không tôi sẽ có vẻ cần thiết^^ –

1

tôi sẽ ra ở cánh một ở đây, nhưng tôi nghi ngờ vấn đề là với Chủ đề của bạn destructor:

virtual ~Thread() { 
    catch_up(); 
    delete m_thread; 
} 

Nếu thread có không bắt đầu được nêu ra, gọi catch_up() trong destructor sẽ bắt đầu thread boost bằng cách sử dụng vtable của Thread thay vì A, như trong C++ tại điểm của destructor vtable phù hợp với phạm vi của loại destructor, không phải là vtable có nguồn gốc nhất.

+0

Tôi nghĩ rằng mới phân bổ xử lý chủ đề sau khi tạo nó phải không? Vì vậy, kiểm tra trong catch_up() nếu m_thread bằng NULL đủ để bảo vệ nó trong trường hợp destructor là nhanh hơn so với việc tạo ra các chủ đề. –

+0

Tôi đang đề cập đến destructor của Thread, không tăng :: destructor của thread. – MSN

+0

Tôi biết, tôi cũng đang nói về điều đó. Nhưng bây giờ tôi hiểu, tôi nghĩ rằng bạn đã chỉ ra nó quá, xin lỗi vì đã hiểu lầm, xấu của tôi;) –

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