2012-02-27 9 views
5

Tengo un proyecto de Visual Studio 2008 C++ usando Boost 1.47.0 donde necesito obtener el ID nativo de Windows de un boost :: thread para pasar a PostThreadMessage.Obteniendo el ID de un boost :: thread para PostThreadMessage

En Windows Vista y 7, me acaba de hacer esto:

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

Esto está muy bien, pero también necesito mi aplicación para trabajar en XP, donde no existe GetThreadId.

He encontrado que boost: thread almacena el valor de ID de hilo en el miembro de datos privados de boost :: thread :: id thread_data. Puedo llegar a que al hacer algunos moldes desagradables:

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

Pero, comienza a recibir las advertencias del compilador para hacer referencia a un objeto temporal boost::thread::id.

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

¿Hay alguna manera de obtener la identificación? Es muy frustrante ver la información que necesito, pero no poder acceder a ella.

Gracias, PaulH

Respuesta

6

He aquí un artilugio ingenioso/desagradable utilizando una técnica descrita por Johannes Schaub - litb en su blog, Access to private members: Safer nastiness. Todo el crédito debe ir a Johannes. Voy a tener la culpa de su aplicación a un escenario del mundo real (o tal vez usted puede):

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

No estoy seguro de si esto califica como un "buen camino" para obtener la información. Pero funciona sin modificar los encabezados de impulso o las bibliotecas, y el compilador no se queja en absoluto, incluso con advertencias relativamente altas. Probado en:

  • MinGW 4.6.1 -Wall -Wextra con algunas advertencias especialmente ruidosos desactivado - pero no para esta prueba en particular. Están desactivados en mi script genérico de "compilar esta prueba".
  • VC++ 2008 y 2010 con/W4

Aquí una muestra de ejecución que se muestra funciona:

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

Por supuesto, debería ser evidente que esto podría romper si/cuando impulso :: el hilo cambia con el tiempo, pero probablemente no en silencio.


algunas notas explicativas/punteros:

El 'laguna' utilizado en esta técnica está en C++ 03 14.7.2/8 "instanciación explícita":

El acceso habitual las reglas de comprobación no se aplican a los nombres utilizados para especificar instancias explícitas. [Nota: en particular, los argumentos de la plantilla y los nombres utilizados en el declarador de funciones (incluidos tipos de parámetros, tipos de devolución y especificaciones de excepción) pueden ser tipos privados o objetos que normalmente no serían accesibles y la plantilla puede ser un miembro plantilla o función miembro que normalmente no sería accesible.]

de Dave Abrahams tiene un 'quid' que utiliza técnicas similares, junto con los comentarios que explican bastante bien lo que está pasando:

me encontré con que en un comentario que dejó en un artículo anterior sobre el acceso de miembros privados en el blog de Johannes: Access to private members. That's easy!

+0

Esa es la cosa más genial que he visto hoy. Voy a perder las próximas 3 horas tratando de entenderlo. ¡Gracias! – PaulH

+0

+1 para las notas explicativas adicionales. – PaulH

Cuestiones relacionadas