2009-08-19 4 views
1

in Java Ich habe folgende generierten Code:Wie wird eine Objektinstanz bezogen auf einen Thread in C++ abgerufen?

public class B { 
    public void exec(){ 
     X x = (X) Thread.currentThread(); 
     System.out.println(x.value); 
    } 
} 

public class X extends Thread{ 
    public int value; 

    public X(int x){ 
     value = x; 
    } 
    public void run(){ 
     B b = new B(); 
     b.exec(); 
    } 
} 

new X(4).start(); 

Die B exec() Methode ruft den Wert Feld auf den aktuellen Thread (auch Instanz der Klasse X) entspricht.

Gibt es eine Möglichkeit, das gleiche Verhalten in C++ zu simulieren? Hinweis: Ich möchte x nicht als Parameter an die B-Instanz übergeben, da der Code generiert wird.

class B { 
public: 
    void exec(); 
}; 

class X { 
public: 
    int value; 
    X(int x) { 
     value = x; 
    } 
    void run() { 
     B * b = new B(); 
     b->exec(); 
    }  
}; 

void B::exec() { 
    std::cout << ??? << std::endl; 
} 

int main() { 
    X * x = new X(3); 
    boost::thread thr(boost::bind(&X::run, x)); 
    thr.join(); 
} 

Ich weiß nicht, wie die Klasseninstanz auf den Thread im Zusammenhang abzurufen (ich weiß, ich habe nicht ein), irgendwelche Ideen?

Antwort

2

Es ist wahr, dass Sie keine Unterklasse boost::thread können (oder sollten). Sie können thread-local storage verwenden, um Ihre eigenen thread-spezifischen Sachen obwohl zu setzen.

Wahrscheinlich sollten Sie die gleiche Technik für Java-Code verwenden. Java hat ThreadLocal für diesen Zweck.

4

Wenn Sie keine Parameter an B übergeben möchten (was die sauberste Lösung wäre), können Sie threadlokalen Speicher verwenden.

Mit Blick auf Ihren Code im Allgemeinen, werden Sie wahrscheinlich in den Fuß schießen, indem Sie diese strikte 1-zu-1-Zuordnung von Java zu C++ versuchen. In C++ sollten Sie fast nie new aufrufen. Verteilen Sie, wenn möglich, auf dem Stapel. new in C++ ist offensichtlich fehleranfällig (keine Garbage Collection), aber es ist auch sehr langsam im Vergleich zu verwalteten Sprachen wie Java.

Funktoren können als leistungsstärkere Alternative zu Funktionszeigern verwendet werden (z. B. beim Erstellen des Threads) oder einfach zum Ersetzen der allgemeinen Funktionen exec() oder run(). Benennen Sie sie stattdessen operator(), und die Klasse kann als Funktor verwendet werden.

Und in Ihren Konstruktoren sollten Sie die Initialisierungsliste so viel wie möglich verwenden.

Im Folgenden finden Sie die obigen Vorschläge zu Ihrem Code. Natürlich habe ich dem B-Konstruktor ein Argument übergeben. Wenn das keine Option ist, verwenden Sie stattdessen thread local storage.

class B { 
public: 
    explicit B(int value) : value(value) 
    void operator()(); 

private: 
    int value; 
}; 

class X { 
public: 
    int value; 
    X(int x) :value(x) { }// use the initializer list to initialize members 

    void operator()() { 
     B b(value); // allocate B on the stack if possible 
     b(); 
    }  
}; 

void B::operator()() { 
    std::cout << value << std::endl; 
} 

int main() { 
    boost::thread thr(X(3)); 
    thr.join(); 
} 

Natürlich in diesem einfachen Beispiel, Sie nicht wirklich brauchen zwei Klassen an erster Stelle. Sie könnten genauso einfach X komplett entfernt und entfernt haben:

class B { 
public: 
    explicit B(int value) : value(value) 
    void operator()(); 

private: 
    int value; 
}; 

void B::operator()() { 
    std::cout << value << std::endl; 
} 

int main() { 
    boost::thread thr(B(3)); 
    thr.join(); 
} 
Verwandte Themen