I want to name a thread, but unfortunately the pthread_setname_np() on Mac works only inside current thread.
Then I do the wrapper around std::thread with a following constructor:
template <class F, class ... Args>
Thread::Thread(const char* name, F&& f, Args&&... args) {
thread_ = std::thread([name, f, args...]() {
pthread_setname_np(name);
f(args...);
});
}
But it doesn't work with class methods:
error: called object type '<complex type>' is not a function or function pointer
f(args...);
^
In the code like this:
threads_.emplace_back("Name", &Aggregator<T>::DoPop, this, some_arg);
What is a proper way to wrap the std::thread and set the thread name, preserving the whole interface excepting the name argument in the constructor?
You can use std::mem_fn to call a member function. The first argument in args has to be the pointer to the member object.
Example:
#include <thread>
#include <functional>
template <class F, class ... Args>
std::thread thread_factory(const char* name, F&& f, Args&&... args) {
return std::thread([=]{
pthread_setname_np(name);
auto fun = std::mem_fn(f);
fun(args...);
});
}
struct test {
int t(int val) {
return val;
}
};
int main() {
test t;
auto b = thread_factory("name", &test::t, &t, 5);
b.join();
}
you have to bind your member function to a class instance. here's your function presented slightly differently with a (working) test:
#include <iostream>
#include <thread>
template <class F, class ... Args>
std::thread launch_named_thread(const char* name, F&& f, Args&&... args) {
return std::thread([name, f, args...]() {
pthread_setname_np(name);
f(args...);
});
}
struct myclass
{
void thread_loop(int i)
{
std::cout << i << std::endl;
}
};
auto main() -> int
{
myclass x;
auto t = launch_named_thread("hello", std::bind(&myclass::thread_loop, &x, 6));
// this could be:
// auto t = launch_named_thread("hello", std::bind(&myclass::thread_loop, &x, std::placeholders::_1), 6);
// the difference is subtle. i'll leave it to you to work out why
t.join();
return 0;
}
Related
Given the following function:
template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>
{
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared< std::packaged_task<return_type()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
return res;
}
What's the right way to pass a member function to ThreadPool::enqueue as parameter, say the object is:
Foo foo
and the function is:
foo.do_something();
I have tried to use std::bind and std::mem_fn with or without "&" and all failed.
In addition to what #IgorTandetnik has mentioned in the comments, you can also use std::bind with std::mem_fn to pass a member function to your method:
struct Foo
{
void do_something() {}
void do_something_else(int x, int y, std::string str) {}
};
int main()
{
Foo foo;
ThreadPool pool;
auto func_sth = std::bind(std::mem_fn(&Foo::do_something), foo);
auto func_sth_else = std::bind(std::mem_fn(&Foo::do_something_else), foo, 10 , 11, "hi");
pool.enqueue(func_sth);
pool.enqueue(func_sth_else);
return 0;
}
Here some code with holes:
template<typename... Args>
class A
{
typedef function_type = void(*)(Args...);
public:
void set_args(Args&& ... args)
{
// something magic manages to encapsulate
// args in instance of A
}
void apply_args(function_type function)
{
// something magic manages to "retrieve"
// the encapsulated args
function(std::forward<Args>(args)...);
}
};
Would that be somehow possible ?
You can store your template arguments in class data member of std::tuple type and the use std::apply in order to apply stored arguments to provided function.
So, let's say you have an Action class like this:
template <typename... Args>
class Action {
std::tuple<Args...> args_;
public:
Action() = default;
Action(Args&&... args)
: args_(std::forward<Args>(args)...)
{}
void args(Args&&... args) {
args_ = std::make_tuple<Args...>(std::forward<Args>(args)...);
}
template <typename F>
void apply(F&& fun) {
std::apply(std::forward<F&&>(fun), args_);
}
};
where you set arguments through constructor Action action(1, 2, 3); or through separate function action.set(3, 2, 1);.
Then your main function can look like this:
int main() {
Action action(1, 2);
action.apply([](int a, int b) {
std::cout << "a + b = " << (a + b) << std::endl;
});
return 0;
}
Check live example
You can make use of std::tuple and std::apply
#include <iostream>
#include <tuple>
#include <functional>
#include <string>
template <typename... Ts>
class A
{
private:
std::function<void (Ts...)> f;
std::tuple<Ts...> args;
public:
template <typename F>
A(F&& func, Ts&&... args)
: f(std::forward<F>(func)),
args(std::make_tuple(std::forward<Ts>(args)...))
{}
void Invoke()
{
std::apply(f, args);
}
};
template <typename F, typename... Args>
A<Args...> Create(F&& f, Args&&... args)
{
return A<Args...>(std::forward<F>(f), std::forward<Args>(args)...);
}
int main()
{
auto helloWorld = Create([] (std::string a, std::string b) { std::cout << a << ", " << b; }, std::string("Hello"), std::string("World!"));
helloWorld.Invoke();
}
I'm trying to store a member function of an unknown class with unkown arguments to be called later.
I found this code snippet to get the lambda:
template <auto Fn, typename T, typename R = void, typename... Args>
auto get_cb_inner(T* obj, R (T::*)(Args...) const) {
return [obj](Args... args) -> R {
return (obj->*Fn)(std::forward<Args>(args)...);
};
}
template <auto Fn, typename T>
auto get_cb(T* obj) {
return get_cb_inner<Fn, T>(obj, Fn);
}
But I can't figure out how I would store it and then be able to call it during runtime with the correct parameters.
I have a struct like this:
struct Job {
void execute(Data& data, const OtherData& otherData) const {
// do job
}
};
auto exe_fn = get_cb<&Job::execute>(new Job());
What I want to do is to store this "execute" function in a lambda and then store it in a vector-like container (with other functions that may have different arguments) that can be iterated and called on.
EDIT:
Using #KamilCuk code I created this wrapper-struct with no mem leaks/seg faults.
template <typename... Args>
using exec_fn = std::function<void(Args...)>;
template <typename Job>
using job_ptr = std::unique_ptr<Job>;
template <typename J, typename R = void, typename... Args>
struct JobExecuteCaller {
exec_fn<Args...> exec_fn;
job_ptr<J> job_ptr;
JobExecuteCaller (J* job, R (S::*f)(Args...) const)
: job_ptr{job_ptr<J>(job)} {
exec_fn = [this, f](Args... args) -> R {
(job_ptr.get()->*f)(std::forward<Args>(args)...);
};
}
void operator()(Args... args) { exec_fn(args...); }
};
auto process = JobExecuteCaller(new Job(), &Job::execute);
JobExecuteCaller(/*args ... */)
Now I just have to figure out a way to store different kinds of JobExecuteCallers.
You mean you want std::bind?
#include <utility>
#include <new>
#include <iostream>
#include <functional>
struct Job {
void execute(int a, int b) {
std::cout << a << " " << b << std::endl;
}
};
int main() {
auto exe_fn = std::bind(&Job::execute, new Job(),
std::placeholders::_1, std::placeholders::_2);
exe_fn(1, 2);
}
I have fixed your code. You need to pass not only the type of the function member pointer, but also the address of the function member pointer to the function. That way you can call it.
#include <utility>
#include <new>
#include <iostream>
#include <functional>
template <typename T, typename R = void, typename... Args>
auto get_cb(T* obj, R (T::*f)(Args...)) {
return [obj, f](Args... args) -> R {
return (obj->*f)(std::forward<Args>(args)...);
};
}
struct Job {
void execute(int a, int b) {
std::cout << a << " " << b << std::endl;
}
};
int main() {
auto exe_fn = get_cb(new Job(), &Job::execute);
exe_fn(1, 2);
}
Note that both examples leak memory from new Job().
Based on my previous question here Variadic template, function as argument
I have ended up with a simple class below, however how do I use std::invoke or some other method to call Tester::test with Tester::simple as argument? The examples provided at http://en.cppreference.com/w/cpp/utility/functional/invoke#Example were not very helpful for me and I tried many different ways of using std::invoke.
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
int main()
{
Tester t;
std::cout << t.test(t.simple, 3); // how do you modify this line such that the code compiles?
}
Thanks!
One way is to modify the definition of your test() member function like so:
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
We can then pass a member function pointer to test(), with the instance on which the method should be called as the second argument, and then the function arguments themselves:
int main()
{
Tester t;
std::cout << t.test(&Tester::simple, t, 3);
}
The reason this works is because std::invoke has a special overload for pointers-to-members, such that
std::invoke(ptr-to-member, instance, args...);
is called as
(instance.*ptr-to-member)(args...);
which is exactly what we want in this case.
Note, that std::invoke is a part of C++ 17. In case if it is not available, one might implement test function so that it accepts a pointer-to-member-function and an instance of a class:
template<typename F, typename T, typename... Args>
decltype(auto) test(F f, T&& t, Args&&... args) {
return (std::forward<T>(t).*f)(std::forward<Args>(args)...);
}
Now test accepts a pointer-to-member-function as a first argument, an instance of a class as a second argument and an arbitrary number of additional arguments.
Then test might be called like:
Tester t;
std::cout << t.test(&Tester::simple, t, 42);
WANDBOX EXAMPLE
Just to mention yet another possibility, you could wrap the member function call in a lambda and capture the instance t. In C++14 we can use the generic lambda for that, so we don't have to specify the parameters explicitly.
#include <iostream>
#include <utility>
class Tester {
public:
template<typename F, typename... Args>
decltype(auto) test(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...);
}
int simple(int i) { return i; }
};
int main()
{
Tester t;
std::cout << t.test([&t] (auto&&... args) { return t.simple(std::forward<decltype(args)>(args)...); }, 3);
}
I'm trying to subclass std::thread such that a member function of the subclass is executed on the new thread before the caller's passed-in function. Something like the following invalid code:
#include <thread>
#include <utility>
class MyThread : public std::thread {
template<class Func, class... Args>
void start(Func&& func, Args&&... args) {
... // Useful, thread-specific action
func(args...);
}
public:
template<class Func, class... Args>
MyThread(Func&& func, Args&&... args)
: std::thread{[=]{start(std::forward<Func>(func),
std::forward<Args>(args)...);}} {
}
};
g++ -std=c++11 has the following issue with the above code:
MyThread.h: In lambda function:
MyThread.h:ii:jj: error: parameter packs not expanded with '...':
std::forward<Args>(args)...);}}
^
I've tried a dozen different variations in the initializer-list to no avail.
How can I do what I want?
The biggest difficulty I had when I did this before was getting all the behavior of std::thread. It's constructor can take not only a pointer to a free function, but also a class method pointer and then a object of the class as the first argument. There are a number of variations on that: class methods, class function object data members, an object of the class type vs a pointer to an object, etc.
This is for C++14:
class MyThread : public std::thread {
void prolog() const { std::cout << "prolog\n"; }
public:
template <typename... ArgTypes>
MyThread(ArgTypes&&... args) :
std::thread(
[this, bfunc = std::bind(std::forward<ArgTypes>(args)...)]
() mutable {
prolog();
bfunc();
})
{ }
};
If you put the prolog code inside the lambda and it doesn't call class methods, then the capture of this is not needed.
For C++11, a small change is needed because of the lack of capture initializers, so the bind must be passed as an argument to std::thread:
std::thread(
[this]
(decltype(std::bind(std::forward<ArgTypes>(args)...))&& bfunc) mutable {
prolog();
bfunc();
}, std::bind(std::forward<ArgTypes>(args)...))
Here's a test program that also exercises the class member form of std::thread:
int main()
{
auto x = MyThread([](){ std::cout << "lambda\n"; });
x.join();
struct mystruct {
void func() { std::cout << "mystruct::func\n"; }
} obj;
auto y = MyThread(&mystruct::func, &obj);
y.join();
return 0;
}
I haven't checked, but I'm a bit worried that the capture of this, also seen in other solutions, is not safe in some cases. Consider when the object is an rvalue that is moved, as in std::thread t = MyThread(args). I think the MyThread object will go away before the thread it has created is necessarily finished using it. The "thread" will be moved into a new object and still be running, but the captured this pointer will point to a now stale object.
I think you need to insure your constructor does not return until your new thread is finished using all references or pointers to the class or class members. Capture by value, when possible, would help. Or perhaps prolog() could be a static class method.
This should do it (c++11 and c++14 solutions provided):
C++14
#include <thread>
#include <utility>
#include <tuple>
class MyThread : public std::thread {
template<class Func, class ArgTuple, std::size_t...Is>
void start(Func&& func, ArgTuple&& args, std::index_sequence<Is...>) {
// Useful, thread-specific action
func(std::get<Is>(std::forward<ArgTuple>(args))...);
}
public:
template<class Func, class... Args>
MyThread(Func&& func, Args&&... args)
: std::thread
{
[this,
func = std::forward<Func>(func),
args = std::make_tuple(std::forward<Args>(args)...)] () mutable
{
using tuple_type = std::decay_t<decltype(args)>;
constexpr auto size = std::tuple_size<tuple_type>::value;
this->start(func, std::move(args), std::make_index_sequence<size>());
}
}
{
}
};
int main()
{
auto x = MyThread([]{});
}
In C++17 it's trivial:
#include <thread>
#include <utility>
#include <tuple>
#include <iostream>
class MyThread : public std::thread {
public:
template<class Func, class... Args>
MyThread(Func&& func, Args&&... args)
: std::thread
{
[this,
func = std::forward<Func>(func),
args = std::make_tuple(std::forward<Args>(args)...)] () mutable
{
std::cout << "execute prolog here" << std::endl;
std::apply(func, std::move(args));
std::cout << "execute epilogue here" << std::endl;
}
}
{
}
};
int main()
{
auto x = MyThread([](int i){
std::cout << i << std::endl;
}, 6);
x.join();
}
C++11 (we have to facilitate moving objects into the mutable lambda, and provide the missing std::index_sequence):
#include <thread>
#include <utility>
#include <tuple>
namespace notstd
{
using namespace std;
template<class T, T... Ints> struct integer_sequence
{};
template<class S> struct next_integer_sequence;
template<class T, T... Ints> struct next_integer_sequence<integer_sequence<T, Ints...>>
{
using type = integer_sequence<T, Ints..., sizeof...(Ints)>;
};
template<class T, T I, T N> struct make_int_seq_impl;
template<class T, T N>
using make_integer_sequence = typename make_int_seq_impl<T, 0, N>::type;
template<class T, T I, T N> struct make_int_seq_impl
{
using type = typename next_integer_sequence<
typename make_int_seq_impl<T, I+1, N>::type>::type;
};
template<class T, T N> struct make_int_seq_impl<T, N, N>
{
using type = integer_sequence<T>;
};
template<std::size_t... Ints>
using index_sequence = integer_sequence<std::size_t, Ints...>;
template<std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>;
}
template<class T>
struct mover
{
mover(T const& value) : value_(value) {}
mover(T&& value) : value_(std::move(value)) {}
mover(const mover& other) : value_(std::move(other.value_)) {}
T& get () & { return value_; }
T&& get () && { return std::move(value_); }
mutable T value_;
};
class MyThread : public std::thread {
template<class Func, class ArgTuple, std::size_t...Is>
void start(Func&& func, ArgTuple&& args, notstd::index_sequence<Is...>) {
// Useful, thread-specific action
func(std::get<Is>(std::forward<ArgTuple>(args))...);
}
public:
template<class Func, class... Args>
MyThread(Func&& func, Args&&... args)
: std::thread()
{
using func_type = typename std::decay<decltype(func)>::type;
auto mfunc = mover<func_type>(std::forward<Func>(func));
using arg_type = decltype(std::make_tuple(std::forward<Args>(args)...));
auto margs = mover<arg_type>(std::make_tuple(std::forward<Args>(args)...));
static_cast<std::thread&>(*this) = std::thread([this, mfunc, margs]() mutable
{
using tuple_type = typename std::remove_reference<decltype(margs.get())>::type;
constexpr auto size = std::tuple_size<tuple_type>::value;
this->start(mfunc.get(), std::move(margs).get(), notstd::make_index_sequence<size>());
});
}
};
int main()
{
auto x = MyThread([](int i){}, 6);
x.join();
}