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();
}
this
as parameter forrun
then you can basically call whatever method you like. Wont be the best solution, but simpler than what you currecntly have – 463035818_is_not_a_numberstd::placeholders::_1
to bind function, when your bound object is invoked with no parameters ? Remove it and your code compiles. – rafix07auto l = new auto([&callable, args...]{ callable(args...); });
Of course you must make sure thecallable
does not vanish before it is used. This applies to both attempts. IMNSHO callable objects should always be passed by value. In additionm_joinable
is not set correctly 'causepthread_create
returns 0 on success ;) – n. 1.8e9-where's-my-share m.