I understand that pthread_create accepts a void*(*)(void*) argument and a void*, so I have made 2 (failed) attempts to wrap a Function and Args...:
a. Creating a C-style void *run(void*) function that will call an std::function object that was passed to it:
class thread { public: typedef std::function<void()> functor_t; static void* run(void* f) { functor_t* functor = (functor_t*)f; (*functor)(); delete functor; return nullptr; } template<typename Callable, typename... Args> explicit thread(size_t stack_size, Callable && callable, Args&&... args) { auto task_ptr = std::make_shared<std::packaged_task<decltype(callable(args...))()>>( std::bind(std::forward<Callable>(callable), std::placeholders::_1, std::forward<Args>(args)...) ); functor_t* functor = new functor_t([task_ptr]() { (*task_ptr)(); }); pthread_attr_t attr = { 0}; if (pthread_attr_init(&attr) == 0) { m_joinable = pthread_attr_setstacksize(&attr, stack_size) == 0 && pthread_create(&m_id, &attr, &run, functor); pthread_attr_destroy(&attr); } } private: pthread_t m_id = -1 ; bool m_joinable = false ; }; This causes the following error in GCC 4.8.5:
/usr/include/c++/4.8.2/functional: In instantiation of ‘struct std::_Bind_simple(std::_Placeholder<1>, int))(int*)> >()>’: /usr/include/c++/4.8.2/future:1284:55: required from ‘void std::__future_base::_Task_state<_Fn, _Alloc, _Res(_Args ...)>::_M_run(_Args ...) [with _Fn = std::_Bind(std::_Placeholder<1>, int))(int*)>; _Alloc = std::allocator; _Res = void; _Args = {}]’ thread.cpp:17:1: required from here /usr/include/c++/4.8.2/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of(std::_Placeholder<1>, int))(int*)> >()>’ typedef typename result_of<_Callable(_Args...)>::type result_type; ^ /usr/include/c++/4.8.2/functional:1727:9: error: no type named ‘type’ in ‘class std::result_of(std::_Placeholder<1>, int))(int*)> >()>’ _M_invoke(_Index_tuple<_Indices...>) ^
b. Following this example http://coliru.stacked-crooked.com/a/a6c607514601b013
class thread { public: template< typename Callable, typename... Args > explicit thread(size_t stack_size, Callable&& callable, Args&&... args ) { auto l = new auto([=]{ callable(args...); }); auto te = [](void* rp) -> void* { auto p = reinterpret_cast<decltype(l)>(rp); (*p)(); delete p; return nullptr; }; pthread_attr_t attr = { 0}; if (pthread_attr_init(&attr) == 0) { m_joinable = pthread_attr_setstacksize(&attr, stack_size) == 0 && pthread_create(&m_id, &attr, te, l); pthread_attr_destroy(&attr); } } private: pthread_t m_id = -1 ; bool m_joinable = false ; }; This is supposed to work in clang, but fails in GCC 4.8.5 with:
In file included from thread.cpp:2:0: thread.h: In lambda function: thread.h:82:37: error: parameter packs not expanded with ‘...’: auto l = new auto([=]{ callable(args...); }); ^ thread.h:82:37: note:
‘args’ thread.h:82:41: error: expansion pattern ‘args’ contains no argument packs auto l = new auto([=]{ callable(args...); }); ^ thread.h: In instantiation of ‘struct thread::thread(size_t, Callable&&, Args&& ...) [with Callable = void ()(int); Args = {int*}; size_t = long unsigned int]::__lambda4’: thread.h:82:48:
required from ‘thread::thread(size_t, Callable&&, Args&& ...) [with Callable = void ()(int); Args = {int*}; size_t = long unsigned int]’ thread.cpp:14:32: required from here thread.h:82:37: error: using invalid field ‘thread::thread(size_t, Callable&&, Args&& ...)::__lambda4::__args’ auto l = new auto([=]{ callable(args...); }); ^ thread.h:83: confused by earlier errors, bailing out
Both ran with the follwing main:
int g=5; void run(int *i) { printf("t\n"); } int main() { gs_thread t(256*1024, &run, &g); printf("m\n"); t.join(); }
thisas parameter forrunthen you can basically call whatever method you like. Wont be the best solution, but simpler than what you currecntly havestd::placeholders::_1to bind function, when your bound object is invoked with no parameters ? Remove it and your code compiles.auto l = new auto([&callable, args...]{ callable(args...); });Of course you must make sure thecallabledoes not vanish before it is used. This applies to both attempts. IMNSHO callable objects should always be passed by value. In additionm_joinableis not set correctly 'causepthread_createreturns 0 on success ;)