2012-02-27 3 views
5

У меня есть проект Visual Studio 2008 C++ с использованием Boost 1.47.0, где мне нужно получить собственный идентификатор Windows для потока boost :: thread, чтобы перейти к PostThreadMessage.Получение идентификатора boost :: thread для PostThreadMessage

В Windows Vista и 7, я бы просто сделать это:

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

Это прекрасно, но мне также нужно мое приложение работать в XP, где GetThreadId не существует.

Я нашел, что boost: thread хранит значение идентификатора потока в boost :: thread :: Личные данные пользователя id thread_data. Я могу добраться до этого, делая некоторые неприятные слепки:

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

Но, я начала получать предупреждения компилятора для ссылки на временный boost::thread::id объект.

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

Есть ли хороший способ получить идентификатор? Очень жаль видеть часть данных, в которой я нуждаюсь, но не могу ее понять.

Спасибо, PaulH

ответ

6

Вот умный/противный хак с использованием методики, описанной Johannes Schaub - litb на своем блоге, Access to private members: Safer nastiness. Все кредиты должны отправиться в Йоханнес. Я возьму на себя вину за ее применения в реальной ситуации (или, может быть, вы можете):

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

Я не уверен, если это квалифицируется как «хороший путь», чтобы получить информацию. Но он работает без изменения заголовков или библиотек форматирования, и компилятор вообще не жалуется - даже с относительно высокими предупреждениями. Проверено на:

  • MinGW 4.6.1 -Wall -Wextra с несколькими особенно шумными предупреждениями выключено - но не для этого теста, в частности. Они отключены в моем общем сценарии «скомпилировать этот тест».
  • VC++ 2008 и 2010 с/W4

Вот пример работы, который показывает, что он работает:

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

Конечно, это должно пойти, не говоря, что это может сломаться, если/когда повышение :: нить меняется со временем, но, вероятно, не тихо.


Некоторых пояснительные примечания/указатели:

'лазейка' используется в этой технике в C++ 03 14.7.2/8 "Явной конкретизации":

Обычным доступ правила проверки не применяются к именам, используемым для указания явных экземпляров . [Примечание: в частности, аргументы шаблона и имена, используемые в деклараторе функции (включая типы параметров, типы возвращаемых типов и спецификаций исключений) могут быть частными типами или объектами, которые обычно не доступны, и шаблон может быть членом шаблон или функция-член, которая обычно не была бы доступна .]

Дэйв Абрахамс имеет «суть», который использует подобные методы, наряду с комментариями, которые объясняют довольно хорошо, что происходит:

Я обнаружил, что в комментарии он оставил о предыдущей статье о доступе к частному члену в блоге Johannes: Access to private members. That's easy!

+0

Это самая крутая вещь, которую я видел сегодня. Я буду тратить впустую следующие 3 часа, пытаясь понять это. Благодаря! – PaulH

+0

+1 для дополнительных пояснительных примечаний. – PaulH