views:

122

answers:

2

Hello,

In java I have the following generated code:

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();

The B exec() method retrieves the field value corresponding to the current Thread (also instance of the class X).

Is there a way to simulate the same behavior in C++? Note: I wouldn't like to pass x as a parameter to the B instance because the code is generated.

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();
}

I don't know how to retrieve the class instance related to the thread ( I know I don't have one ), any ideas?

+2  A: 

It's true that you can't (or shouldn't) subclass boost::thread. You can use thread-local storage to put your own thread-specific stuff though.

Arguably, you should use the same technique for Java code. Java has ThreadLocal for that purpose.

Chris Jester-Young
+4  A: 

If you don't want to pass parameters to B (which would have been the cleanest solution), you can use thread-local storage.

Looking at your code in general though, you'll probably be shooting yourself in the foot by trying this strict 1-to-1 mapping from Java to C++.

In C++, you should almost never call new. Allocate on the stack whenever possible. new in C++ is obviously error-prone (no garbage collection), but it's also extremely slow compared to managed languages like Java.

Functors can be used as a more powerful alternative to function pointers (for example when creating your thread), or just to replace generic exec() or run() functions. Name them operator() instead, and the class can be used as a functor.

And in your constructors you should use the initializer list as much as possible.

The following applies the above suggestions to your code. Of course I passed an argument to the B constructor. If that's not an option, use thread local storage instead.

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();
}

Of course in this simple example, you don't really need two classes in the first place. You could just as easily have removed X entirely and done:

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();
}
jalf