2012-02-27 31 views
5

Tôi có một Visual Studio 2008 C++ dự án bằng cách sử dụng Boost 1.47.0 nơi tôi cần để có được Windows ID gốc của một tăng :: thread để vượt qua để PostThreadMessage.Lấy ID của một tăng :: thread cho PostThreadMessage

Trong Windows Vista và 7, tôi sẽ chỉ làm điều này:

DWORD thread_id = ::GetThreadId(mythread.native_handle()); 

này là tốt, nhưng tôi cũng cần ứng dụng của tôi để làm việc trong XP nơi GetThreadId không tồn tại.

Tôi đã nhận thấy rằng tăng: chuỗi lưu trữ giá trị ID luồng trong tăng :: thread :: thành viên dữ liệu riêng tư của id thread_data. Tôi có thể lấy đó bằng cách thực hiện một số phôi khó chịu:

boost::detail::thread_data_base* tdb = *reinterpret_cast< boost::detail::thread_data_base** >(&message_thread.get_id()); 
DWORD thread_id = tdb->id; 

Nhưng, tôi bắt đầu nhận được những cảnh báo trình biên dịch cho tham khảo một đối tượng tạm thời boost::thread::id.

warning C4238: nonstandard extension used : class rvalue used as lvalue 

Có cách nào tốt để lấy ID không? Nó rất bực bội khi thấy mảnh dữ liệu tôi cần, nhưng không thể có được nó.

Cảm ơn, PaulH

Trả lời

6

Dưới đây là một minh/hack nasty sử dụng một kỹ thuật được mô tả bởi Johannes Schaub - litb trên blog của mình, Access to private members: Safer nastiness. Tất cả tín dụng nên đi đến Johannes. Tôi sẽ đổ lỗi cho việc áp dụng nó cho một kịch bản thế giới thực (hoặc có thể bạn có thể):

#include <windows.h> 
#include <iostream> 

#include "boost/thread.hpp" 

using namespace std; 


// technique for accessing private class members 
// 
// from: http://bloglitb.blogspot.com/2011/12/access-to-private-members-safer.html 
// 

template<typename Tag, typename Tag::type M> 
struct Rob { 
    friend typename Tag::type get(Tag) { 
    return M; 
    } 
}; 

struct thread_data_f { 
    typedef unsigned boost::detail::thread_data_base::*type; 

    friend type get(thread_data_f); 
}; 

struct thread_id_f { 
    typedef boost::detail::thread_data_ptr boost::thread::id::*type; 

    friend type get(thread_id_f); 
}; 

template struct Rob<thread_data_f, &boost::detail::thread_data_base::id>; 
template struct Rob<thread_id_f, &boost::thread::id::thread_data>; 

unsigned int get_native_thread_id(boost::thread const& t) 
{ 
    boost::detail::thread_data_ptr thread_data = t.get_id().*get(thread_id_f()); 
    unsigned thread_id = (*thread_data).*get(thread_data_f()); 

    return thread_id; 
} 

// 
// 
// 


// test of get_native_thread_id() 


void thread_func() 
{ 
    cout << "thread running..." << endl; 

    cout << "Windows says my ID is: " << GetCurrentThreadId() << endl; 

    for (;;) { 
     boost::this_thread::yield(); 
    } 
} 


int main() 
{ 
    boost::thread t(thread_func); 

    ::Sleep(2000); 

    cout << "boost says my thread ID is: " << get_native_thread_id(t) << endl; 

    return 0; 
} 

Tôi không chắc chắn nếu điều này đủ điều kiện như là một "cách tốt" để có được thông tin. Nhưng nó hoạt động mà không sửa đổi các tiêu đề hoặc thư viện tăng, và trình biên dịch không phàn nàn gì cả - ngay cả với các cảnh báo tương đối cao. Thử nghiệm trên:

  • MinGW 4.6.1 -Wall -Wextra với một số cảnh báo đặc biệt là bị tắt tiếng ồn - nhưng không dành riêng cho thử nghiệm này. Chúng bị tắt trong kịch bản 'biên dịch thử nghiệm' chung của tôi.
  • VC++ 2008 và 2010 với/W4

Dưới đây là một chạy mẫu cho thấy nó hoạt động:

C:\temp>test 
thread running... 
Windows says my ID is: 5388 
boost says my thread ID is: 5388 

Tất nhiên, nó nên đi mà không nói rằng điều này có thể phá vỡ nếu/khi boost :: thay đổi chủ đề theo thời gian, nhưng có thể không âm thầm.


Một số lưu ý giải thích/con trỏ:

Các 'lỗ hổng' được sử dụng trong kỹ thuật này là trong C++ 03 14.7.2/8 "instantiation Explicit":

Tiếp cận thông thường quy tắc kiểm tra không áp dụng cho các tên được sử dụng để chỉ định instantiations rõ ràng. [Lưu ý: Cụ thể, đối số mẫu và tên được sử dụng trong trình khai báo hàm (bao gồm loại tham số, loại trả lại và thông số ngoại lệ) có thể là loại riêng hoặc đối tượng thường không thể truy cập được và mẫu có thể là thành viên mẫu hoặc chức năng thành viên thường không thể truy cập được .]

Dave Abrahams có 'ý chính' có sử dụng kỹ thuật tương tự cùng với ý kiến ​​mà giải thích khá độc đáo gì đang xảy ra:

tôi thấy rằng trong một chú thích ông rời trên bài viết trước về quyền truy cập của thành viên riêng tư trên blog của Johannes ': Access to private members. That's easy!

+0

Đó là điều tuyệt vời nhất tôi đã thấy hôm nay. Tôi sẽ lãng phí trong 3 giờ tới để cố gắng hiểu nó. Cảm ơn! – PaulH

+0

+1 cho ghi chú giải thích thêm. – PaulH

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