Yuval Ronen wrote:
However, thread1, as returned by create_thread, and the thread_ref returned by current_thread inside the newly spawned thread will indeed be equivalent. They will not only compare equal, but will be interchangeable in every way.
Very good.
Do You plan to change the current implementation ( would be a partial
re-implementation) ?
How about comparing address of thread objects (using the current design)? Will that satisfy your needs?
It would, as long as I have the threads address available from *inside* the thread. But to my understanding boost::thread::thread() does *not* return a globally addressable object. At the end of this posting You will find a compilable but dangerously simplyfied example to demontrate my needs. Its main idea is to make the global boost::thread objects address available through a thread_specific_pointer object. The used approach is far from *elegant* but I didn't find something better. (Having the threads id available from *inside* a static-like call to boost::thread::thread().id() as well as from *outside* by the threads objects method 'id' would simplify the example ...)
As I explained some messages ago, if threads are noncopyable, you can use address of thread objects as a comparable thread_id, while not needing the implementation details (such the Windows handles) at all. If you use this, you need to be careful not to create a thread using the no-parameters constructor, becuase it will entirely ruin my philosophy... ???
// g++ -pthread -W -Wall -lboost_thread-gcc-mt thread_pointer_test.cpp -o thread_pointer_test #include <iostream> #include <set> #include "boost/thread.hpp" #include "boost/thread/tss.hpp" #include "boost/thread/xtime.hpp" boost::thread_specific_ptrboost::thread* current_thread_; std::setboost::thread* some_global_thread_pointers ; void wait(int sec) { boost::xtime wait_until; boost::xtime_get(&wait_until, boost::TIME_UTC); wait_until.sec += sec; boost::thread::sleep(wait_until); } void some_global_func() { if(current_thread_.get()) { std::cout << "\nsome_global_func uses current_thread_:" << *current_thread_ << std::flush; // in real life some_global_thread_pointers must be protected with mutexes std::setboost::thread*::iterator it = some_global_thread_pointers.find(*current_thread_); if(it != some_global_thread_pointers.end()) std::cout << "\nsome_global_func found myself in some_global_thread_pointers" << std::flush; else std::cout << "\nsome_global_func did not find myself in some_global_thread_pointers" << std::flush; } } struct thread_functor { boost::thread** this_pointer_; thread_functor(boost::thread** address_of_this) : this_pointer_(address_of_this) { } void operator()() { wait(1); std::cout << "\nthis_pointer_:" << this_pointer_; std::cout << "\n*this_pointer_:" << *this_pointer_; if(this_pointer_ && *this_pointer_) { std::cout << "\ninitializing current_thread_ ..." << std::flush; current_thread_.reset(this_pointer_); } else std::cout << "\nfailed to initialize current_thread_" << std::flush; wait(1); // call other functions etc. some_global_func(); std::cout << "\nmy_thread ends" << std::flush; current_thread_.release(); // I'm not really happy with the 'assymetric' need to call this method ;-( } }; int main(int argc, char** argv) { boost::thread *my_thread_1(0),*my_thread_2(0); thread_functor my_functor_1(&my_thread_1),my_functor_2(&my_thread_2); my_thread_1 = new boost::thread(my_functor_1); std::cout << "\n&my_thread_1:" << &my_thread_1 << std::flush; std::cout << "\nmy_thread_1:" << my_thread_1 << std::flush; my_thread_2 = new boost::thread(my_functor_2); std::cout << "\n&my_thread_2:" << &my_thread_2 << std::flush; std::cout << "\nmy_thread_2:" << my_thread_2 << std::flush; wait(2); some_global_thread_pointers.insert(my_thread_1); std::cout << "\ninserted my_thread_1 into some_global_thread_pointers, waiting for my_threads to join" << std::flush; my_thread_1->join(); my_thread_2->join(); delete my_thread_1; delete my_thread_2; std::cout << "\n...bye\n" << std::flush; }