0

I need to check if my boost::thread I've created is running from another thread. This SO post explains you can do this by calling:

boost::posix_time::seconds waitTime(0);
myBoostThread.timed_join(waitTime);

I can't have any critical sections in my client thread. Can I guarantee that timed_join() with 0 time argument be lock free?

Community
  • 1
  • 1
elSnape
  • 302
  • 1
  • 12

2 Answers2

1

No, there is no such guarantee.
Even if the boost implementation is completely lock free (I haven't checked), there is no guarantee that the underlying OS implementation is completely lock free.

That said, if locks were used here, I would find it unlikely that they will cause any significant delay in the application, so I would not hesitate using timed_join unless there is a hard real-time deadline to meet (which does not equate to UI responsiveness).

Bart van Ingen Schenau
  • 15,488
  • 4
  • 32
  • 41
  • Unfortunately my client thread is used for realtime processing; mallocs, locks etc. are completely off limits. – elSnape Jan 25 '13 at 13:57
  • Then I recommend doing your own investigation how `timed_join` and the functions below it are implemented (including what the OS guarantees) for your platform. – Bart van Ingen Schenau Jan 25 '13 at 16:22
1

Boost.Thread provides no guarantees about a lock-free timed_join(). However, the implementation, which is always subject to change:

  • Boost.Thread acquires a mutex for pthreads, then performs a timed wait on a condition variable.
  • Boost.Thread calls WaitForMultipleObjects for windows. Its documentation indicates that it will always return immediately. However, I do not know if the underlying OS implementation is lock-free.

For an alternative, consider using atomic operations. While Boost 1.52 does not currently provide a public atomic library, both Boost.Smart_Ptr and Boost.Interprocess have atomic integers within their detail namespace. However, neither of these guarantee lock-free implementations, and one of the configurations for Boost.Smart_Ptr will lock with pthread mutex. Thus, you may need to consult your compiler and system's documentation to identify a lock-free implementation.

Nevertheless, here is a small example using boost::detail::atomic_count:

#include <boost/chrono.pp>
#include <boost/detail/atomic_count.hpp>
#include <boost/thread.hpp>

// Use RAII to perform cleanup.
struct count_guard
{
  count_guard(boost::detail::atomic_count& count) : count_(count) {}
  ~count_guard() { --count_; }
  boost::detail::atomic_count& count_;
};

void thread_main(boost::detail::atomic_count& count)
{
  // Place the guard on the stack. When the thread exits through either normal
  // means or the stack unwinding from an exception, the atomic count will be
  // decremented.
  count_guard decrement_on_exit(count);
  boost::this_thread::sleep_for(boost::chrono::seconds(5));
}

int main()
{
  boost::detail::atomic_count count(1);
  boost::thread t(thread_main, boost::ref(count));

  // Check the count to determine if the thread has exited.
  while (0 != count)
  {
    std::cout << "Sleeping for 2 seconds." << std::endl;
    boost::this_thread::sleep_for(boost::chrono::seconds(2));
  }
}

In this case, the at_thread_exit() extension could be used as an alternative to using RAII.

Tanner Sansbury
  • 51,153
  • 9
  • 112
  • 169