Boost logo

Boost Users :

Subject: [Boost-users] boost::thread::attributes reference overload?
From: Anthony Foiani (tkil_at_[hidden])
Date: 2013-06-13 01:16:15


Greetings.

I have a class that wraps a boost::thread object, and I would like to
specify certain thread attributes at construction time.

My first attempt looked basically like this:

    struct my_thread
    {

        static boost::thread::attributes getThreadAttr()
        {
            boost::thread::attributes attrs;
            attrs.set_stack_size( 256 * 1024 );
            return attrs;
        }

        my_thread( Runnable func )
            : thread_( getThreadAttr(), func )
        {}

        boost::thread thread_;
    };

But that fails:

    g++ -std=c++0x -o thread-attr thread-attr.cpp \
        -lboost_thread-mt -lboost_system -pthread
    ...
    /usr/include/boost/thread/detail/thread.hpp:191:9: note: \
      template argument deduction/substitution failed:
        thread-attr.cpp:48:42: note: cannot convert ¡my_thread::getThreadAttr()()¢ (type \
          ¡boost::thread::attributes {aka boost::thread_attributes}¢) to type
          ¡boost::thread::attributes& {aka boost::thread_attributes&}¢

Replacing 'getThreadAttr' with a method that returns a non-const
reference to internal static variables allows the program to compile
and run successfully:

    static boost::thread::attributes & getThreadAttr()
    {
        static boost::thread::attributes attrs;
        static bool init = false;

        if ( ! init )
        {
            attrs.set_stack_size( 256 * 1024 );
            init = true;
        }

        return attrs;
    }

The full program, with Linux compile lines, can be found at the bottom
of this message and also at:

    http://foiani.home.dyndns.org/~tony/boost/thread-attr.cpp

I did find a closely-related question on StackOverflow:

    http://stackoverflow.com/questions/13868619

Where Vicente replied (http://stackoverflow.com/a/13894968/784478):

    The needed overload

        template <class F, class Arg, class ...Args>
        thread(attributes const& attrs, F&& f, Arg&& arg, Args&&... args)

    is defined only if the compiler supports variadic templates and
    rvalue references. This could explain your problem.

    I guess the documentation could be improved to signal this
    clearly. Please could you create a Trac ticket to follow this
    issue?

However, the compiler I'm using (g++ 4.7.2) has supported both of
these features for years. According to this page:

    http://gcc.gnu.org/projects/cxx0x.html

g++ has supported both of these features since 4.3.

Josef_K (on freenode IRC #boost channel) was kind enough to try the
sample code in their own environment, and they encountered the same
errors on both g++ 4.8.1 and clang 3.4.

The most likely explanation is that I'm doing something stupid. If
anyone has the time to hit me with the clue-by-four, I would
appreciate it.

There is the possibility that Boost.Thread v4 fixes this (I'm on
1_51_0, which is Boost.Thread v3.0.1). I'd rather not try to
transition libraries at this point, but if it has been fixed,
confirmation would be welcome.

For now, I'll most likely implement the "return reference to internal
static" method in my project. It's a bit racy, but since I do all my
thread creation through this one routine, I should be able to manage
it.

Anyway. I'm left feeling that there is a gap somewhere; whether it's
in my understanding, in the older version of Boost.Threads, in
compiler support / quirks, or elsewhere, I don't know.

Regardless, thanks for the excellent library, and happy hacking!

Best regards,
Anthony Foiani

Sample program follows:

========================================================================

// this should work:
// g++ -std=c++0x -o thread-attr thread-attr.cpp -lboost_thread-mt -lboost_system -pthread
//
// this explodes:
// g++ -std=c++0x -o thread-attr thread-attr.cpp -DRVALUE_REFERENCE_DOOM -lboost_thread-mt -lboost_system -pthread

#include <iostream>

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

typedef boost::function< void ( void ) > Runnable;

struct my_thread
{

#ifdef RVALUE_REFERENCE_DOOM

    // this doesn't work.
    static boost::thread::attributes getThreadAttr()
    {
        boost::thread::attributes attrs;
        attrs.set_stack_size( 256 * 1024 );
        return attrs;
    }

#else

    // this does work, but needs more structure before it can be
    // considered safe.
    static boost::thread::attributes & getThreadAttr()
    {
        static boost::thread::attributes attrs;
        static bool init = false;

        if ( ! init )
        {
            attrs.set_stack_size( 256 * 1024 );
            init = true;
        }

        return attrs;
    }

#endif

    my_thread( Runnable func )
        : thread_( getThreadAttr(), func )
    {}

    void join()
    {
        thread_.join();
    }

    boost::thread thread_;
};

void foo()
{
    std::cout << "foo!" << std::endl;
}

int main( int argc, char * argv [] )
{
    my_thread t( foo );
    t.join();

    return 0;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net