c ++ - Få ID af en boost :: tråd til PostThreadMessage

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har et Visual Studio 2008 C ++ projekt ved hjælp af Boost 1.47.0, hvor jeg har brug for at få det oprindelige Windows ID af en boost :: tråd til at overføre til PostThreadMessage.


I Windows Vista og 7, ville jeg bare gøre dette:


DWORD thread\_id = ::GetThreadId( mythread.native\_handle() );


Dette er fint, men jeg har også brug for min app til at arbejde i XP, hvor GetThreadId ikke eksisterer.


Jeg har fundet denne boost: tråd gemmer tråd ID værdien i boost :: thread :: id's private data medlem thread\_data. Jeg kan komme til det ved at lave nogle ubehagelige casts:


boost::detail::thread\_data\_base* tdb = *reinterpret\_cast< boost::detail::thread\_data\_base** >( &message\_thread.get\_id() );
DWORD thread\_id = tdb->id;


Men jeg begynder at få compiler advarsler til at referere til en midlertidig boost::thread::id objekt.


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


Er der en god måde at få id'et til? Det er meget frustrerende at se det stykke data, jeg har brug for, men ikke kunne få det.


Tak,
PaulH

Bedste reference


Her er en smart/uhyggelig hack ved hjælp af en teknik, der beskrives af Johannes Schaub - på hans blog, Adgang til private medlemmer: Sikre nastiness. Alle kreditter skal gå til Johannes. Jeg tager skylden på at anvende den på en real-world scenarie (eller måske du kan): [11]


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


Jeg er ikke sikker på, om dette kvalificerer som en 'god måde' for at få informationen. Men det virker uden at ændre boost headers eller biblioteker, og kompilatoren klager slet ikke overhovedet - selv med relativt høje advarsler. Testet på:



  • MinGW 4.6.1 -Wall -Wextra med nogle få specielt støjende advarsler slået fra - men ikke specielt til denne test. De 'slås fra i mit generiske' compile this test 'script.

  • VC ++ 2008 og 2010 med/W4



Her er en prøvekørsel, der viser, at den virker:


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


Det skal selvfølgelig sige, at dette kan gå i stykker, hvis/når forstærker :: Tråd ændres over tid, men sandsynligvis ikke stille.





Nogle forklarende noter/pointers:


Det 'smuthul', der anvendes i denne teknik, findes i C ++ 03 14.7.2/8 'Explicit instantiation':



  De sædvanlige adgangskontrolregler gælder ikke for navne, der bruges til at angive
  eksplicit instantiations. [[Bemærk: Specielt skabelonargumenterne
  og navne der anvendes i funktionsdeklaratoren (herunder parametertyper,
  returtyper og undtagelsespecifikationer) kan være private typer eller
  objekter, som normalt ikke ville være tilgængelige, og skabelonen kan være
  en medlemskabel eller medlemsfunktion, som normalt ikke ville være
  tilgængelig.]]



Dave Abrahams har et 'kerne', der bruger lignende teknikker sammen med kommentarer, der forklarer ret pænt, hvad der foregår:



  • https://gist.github.com/1528856



Jeg fandt ud af, at han i en kommentar efterlod en tidligere artikel om adgang til private medlemmer på Johannes 'blog: Adgang til private medlemmer. Det er nemt! [12] [13]