2012-02-27 8 views
5

Mam projekt Visual Studio 2008 C++ za pomocą Boost 1.47.0, gdzie muszę uzyskać macierzysty identyfikator Windows boost :: wątek, aby przekazać do PostThreadMessage.Uzyskiwanie ID boost :: wątku dla PostThreadMessage

W systemie Windows Vista i 7, ja po prostu to zrobić:

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

To jest w porządku, ale muszę także moją aplikację do pracy w XP gdzie GetThreadId nie istnieje.

Znalazłem to zwiększenie: wątek przechowuje wartość identyfikatora wątku w boost :: thread :: id's private data member thread_data. Mogę dostać się że wykonując kilka nieprzyjemnych odlewane:

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

Ale ja zaczynam się ostrzeżenia kompilatora dla przedstawieniu tymczasowego boost::thread::id obiekt.

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

Czy istnieje dobry sposób na uzyskanie identyfikatora? To bardzo frustrujące, gdy dostrzegam dane, których potrzebuję, ale nie mogę się do nich dostać.

Dzięki PaulH

Odpowiedz

6

Oto sprytny/paskudny hack, stosując technikę opisaną przez Johannes Schaub - litb na swoim blogu, Access to private members: Safer nastiness. Wszystkie zasługi powinny należeć do Johannesa. Wezmę winę za stosowanie go do świata rzeczywistego scenariusza (a może to tylko możliwe):

#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; 
} 

Nie jestem pewien, czy to kwalifikuje się jako „dobrej drodze”, aby uzyskać informacje. Ale działa bez modyfikowania nagłówków i bibliotek doładowania, a kompilator w ogóle nie narzeka - nawet przy stosunkowo wysokich ostrzeżeniach. Przetestowano:

  • MinGW 4.6.1 -Wall -Wextra z kilkoma szczególnie hałaśliwymi ostrzeżeniami wyłączonymi - ale nie dla tego testu w szczególności. Są wyłączone w moim ogólnym "kompilacji tego testu".
  • VC++ 2008 i 2010 z/W4

Tutaj prowadzony próbka, która pokazuje to działa:

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

Oczywiście, powinno to iść oczywistą, że to może pęknąć, jeśli/kiedy boost :: wątek zmienia się w czasie, ale prawdopodobnie nie jest cichy.


Niektóre objaśniające notatki/wskaźniki:

do 'luka' stosowane w tej technice jest w C++ 03 14.7.2/8 "Explicit konkretyzacji":

Zazwyczaj dostępu Reguły sprawdzania nie mają zastosowania do nazw używanych do określania jawnych instancji w postaci . [Uwaga: W szczególności, argumenty szablonu i nazwy używane w deklaratorze funkcji (w tym typy parametrów, typy zwrotów i specyfikacje wyjątków ) mogą być obiektami prywatnymi lub obiektami, które normalnie nie byłyby dostępne, a szablon może być członkiem szablon lub element członkowski, który normalnie nie byłby dostępny.]

Dave Abrahams ma „sens”, który używa podobnych technik wraz z uwagami, które wyjaśniają całkiem ładnie, co się dzieje:

Okazało się, że w komentarzu wyjechał w poprzednim artykule na temat dostępu prywatnego członka na blogu Johannesa: Access to private members. That's easy!

+0

To najfajniejsza rzecz, jaką widziałem dzisiaj. Zmarnuję kolejne 3 godziny, próbując to zrozumieć. Dzięki! – PaulH

+0

+1 za dodatkowe uwagi objaśniające. – PaulH

Powiązane problemy