4

With boost::thread how do I get a pointer to the boost::thread which is currently executing my function, from within that function?

The following does not compile for me:

boost::thread *currentThread = boost::this_thread;
Christopher Oezbek
  • 23,994
  • 6
  • 61
  • 85
Rella
  • 65,003
  • 109
  • 363
  • 636

4 Answers4

3

You can use boost::this_thread to reference the same thread you use it in.

See http://www.boost.org/doc/libs/1_41_0/doc/html/thread/thread_management.html

Prime
  • 4,081
  • 9
  • 47
  • 64
  • so in some function I would write `boost::thread *curentThread = boost::this_thread`? – Rella Jul 16 '11 at 04:44
  • 1
    Not exactly... Its actually a namespace that contains functions that act on "this thread". What you do is call functions from that namespace. For instance, you can get the ID of "this thread" with boost::this_thread::get_id() and it returns an object of boost::thread::id for "this thread" – Prime Jul 16 '11 at 05:30
3

You have to be careful because boost::thread is a movable type. Consider the following:

boost::thread
make_thread()
{
    boost::thread thread([](boost::thread* p)
    {
        // here p points to the thread object we started from
    }, &thread);
    return thread;
}

// ...
boost::thread t = make_thread();
// if the thread is running by this point, p points to an non-existent object

A boost::thread object is conceptually associated to a thread but is not canonically associated to it, i.e. during the course of the thread more than one thread objects could have been associated with it (just not more than one at a given time). That's partly why boost::thread::id is here. So what is it you want to achieve exactly?

Luc Danton
  • 34,649
  • 6
  • 70
  • 114
  • Well... I end up with a map of boost::thread::ids to boost::thread *. And btw is it possible to for example delete (stop\interrupt) thread from another thread only by its id? – Rella Jul 16 '11 at 13:40
  • @Kiss No. If you correctly maintain the map (i.e. the pointer to `boost::thread` is always valid, and presumably points to the thread currently associated to the `id`) then it is correct to do `the_map[the_id]->interrupt()`. You could have used proper communication mechanisms though. – Luc Danton Jul 16 '11 at 13:45
0

If you scour the Boost Thread documentation in its entirety (http://www.boost.org/doc/libs/release/doc/html/thread.html, or http://www.boost.org/doc/libs/1_60_0/doc/html/thread.html if that first link is broken), you'll find that there is no function provided to get a pointer to the boost::thread object that represents the current thread.

You can solve this problem on your own, however; one solution would be to use a map, mapping boost::thread:ids to boost:thread*s, and then access that map from within your thread to get the pointer.

For example:

#include <cstdio>
#include <map>

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>

std::map<boost::thread::id, boost::thread*> threadsMap;
boost::mutex threadsMapMutex;  // to synchronize access to the map

boost::mutex stdoutMutex;  // to synchronize access to stdout

void thread_function()
{
    threadsMapMutex.lock();

    // get a pointer to this thread
    boost::thread::id id = boost::this_thread::get_id();
    boost::thread* thisThread = threadsMap.find(id)->second;

    threadsMapMutex.unlock();

    // do whatever it is that you need to do with the pointer

    if(thisThread != NULL)
    {
        stdoutMutex.lock();
        printf("I have a pointer to my own thread!\n");
        stdoutMutex.unlock();
    }
}

int main()
{
    threadsMapMutex.lock();

    // create the threads
    boost::thread thread1(&thread_function);
    boost::thread thread2(&thread_function);

    // insert the threads into the map
    threadsMap.insert(std::pair<boost::thread::id, boost::thread*>(thread1.get_id(), &thread1));
    threadsMap.insert(std::pair<boost::thread::id, boost::thread*>(thread2.get_id(), &thread2));

    threadsMapMutex.unlock();

    // join the threads
    thread1.join();
    thread2.join();

    return 0;
}

P.S. I just noticed that you posted in a comment that you're actually using this solution, after having already written this. Oh well--I still find it useful and complete to officially post the answer to your question, as well as (working) sample code for a potential solution.

Community
  • 1
  • 1
villapx
  • 1,743
  • 1
  • 15
  • 31
0

Instead of using additional map, it is possible to bind the created thread pointer to thread function directly. As @luc-danton mentioned, you must be sure that given pointer is valid as long as thread is alive.

E.g, when using boost::thread_group, interanlly threads are stored as raw pointers in the list, so thread pointer is valid all time.

void thread_func(boost::shared_future<boost::thread*> thread_ptr_future)
{
    // Do not continue until this thread pointer is not set.
    boost::thread* this_thread_ptr = thread_ptr_future.get();
    std::cout << "This thread pointer gained: " << this_thread_ptr << std::endl;
    //... continue thread content with valid this thread pointer.
}

boost::thread_group m_threads; ///< Instead of manually creating the list of threads.

void start_new_thread()
{
    boost::promise<boost::thread*> thr_promise;
    boost::shared_future<boost::thread*> thr_future(thr_promise.get_future());
    boost::thread* thread_ptr = 
        m_threads.create_thread(boost::bind(thread_func,  thr_future));
    thr_promise.set_value(thread_ptr);
}

Michał Jaroń
  • 469
  • 4
  • 11