How to pass function parameters to boost::thread_groups::create_thread() - c++

I am new to Boost.Threads and am trying to understand how to pass function arguments to the boost::thread_groups::create_thread() function. After reading some tutorials and the boost documentations, I understand that it is possible to simply pass the arguments to this function but I can't get this method to work.
The other method I read about is to use functors to bind the parameters to my function but that would create copies of the arguments and I strictly require that const references be passed since the arguments will be big matrices(this I plan to do by using boost::cref(Matrix) once I get this simple example to work).
Now, let's get down to the code:
void printPower(float b, float e)
{
cout<<b<<"\t"<<e<<"\t"<<pow(b,e)<<endl;
boost::this_thread::yield();
return;
}
void thr_main()
{
boost::progress_timer timer;
boost::thread_group threads;
for (float e=0.; e<20.; e++)
{
float b=2.;
threads.create_thread(&printPower,b,e);
}
threads.join_all();
cout << "Threads Done" << endl;
}
This doesn't compile with the following error:
mt.cc: In function âvoid thr_main()â:
mt.cc:46: error: no matching function for call to âboost::thread_group::create_thread(void (*)(float, float), float&, float&)â
/usr/local/boost_1_44_0/include/boost/thread/detail/thread.hpp: In member function âvoid boost::detail::thread_data<F>::run() [with F = void (*)(float, float)]â:
mt.cc:55: instantiated from here
/usr/local/boost_1_44_0/include/boost/thread/detail/thread.hpp:61: error: too few arguments to function
What am I doing wrong?

You can't pass arguments to boost::thread_group::create_thread() function, since it gets only one argument. You could use boost::bind:
threads.create_thread(boost::bind(printPower, boost::cref(b), boost::cref(e)));
# ^ to avoid copying, as you wanted
Or, if you don't want to use boost::bind, you could use boost::thread_group::add_thread() like this:
threads.add_thread(new boost::thread(printPower, b, e));

For more flexibility you can use:
-Lambda functions (C++11): What is a lambda expression in C++11?
threads.create_thread([&b,&e]{printPower(b,e);});
-Functors that store the arguments as const references.
struct PPFunc {
PPFunc(const float& b, const float& e) : mB(b), mE(e) {}
void operator()() { printPower(mB,mE); }
const float& mB;
const float& mE;
};
-std::bind (C++11) or boost::bind

Related

Passing the address of a function template

Consider the following function:
template <int node>
void RemainingEnergyTrace (double oldValue, double newValue)
{
std::stringstream ss;
ss << "Energy_" << node << ".log";
static std::fstream f (ss.str().c_str(), std::ios::out);
f << Simulator::Now().GetSeconds() << " Remaining energy=" << newValue << std::endl;
}
Note the template definition of the function int node. I try to pass the address of this function in main():
int inc = 0;
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
which generates the following errors:
error: the value of ‘inc’ is not usable in a constant expression
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
^
error: no matching function for call to ‘MakeCallback(<unresolved overloaded function type>)’
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
^
However, the following statement works:
eSources.Get (0)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<0>));
In summary, an actual number works, but when an integer variable is passed in the template format, it does not. Is it because the integer variable has to be of const type (as suggested by the error)?
I am trying to actually run a loop and pass the address of the function for different integer values. How can I make this work?
for(int inc = 0; inc<nWifi; inc++)
{
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
}
In short, you can't. Since templates are expanded at compilation time, you need to provide the values at compilation time as well. If nWifi is a value that's only available at runtime, you need to use a regular parameter:
void RemainingEnergyTrace (double oldValue, double newValue, int node);
If you want then to create partially applied functions to pass to your MakeCallback, you can create them using lambdas:
for(int inc = 0; inc<nWifi; inc++)
{
auto callback = [=](double oldVal, double newVal) {
RemainingEnergyTrace(oldVal, newVal, inc);
};
...
}
But this won't decay to a function pointer, so you might need to change your MakeCallback API to e.g. use std::function (which is a preferred method nowadays) or to take an additional parameter1, or alternatively use some library that will provide the delegate functionality you need.
1Typically, a C or C++ API that takes function pointers would also take an additional void* parameter to store alongside the function pointer. Then, when calling, the pointer would be passed to that function, and store the necessary closure data (in your case, it could point to the inc value residing somewhere in memory). Without knowing how the MakeCallback works, it's impossible to tell what would be the best solution here.

Can you help me to understand why this bind works?

I'm trying to understand bind and pre-fill functions in C++.
Here's my example:
#include <iostream>
#include <functional>
#include <vector>
class Voice
{
public:
double mValue;
private:
};
class VoiceManager
{
public:
VoiceManager() { }
~VoiceManager() { }
typedef std::function<void(Voice &)> VoiceChangerFunction;
inline void UpdateVoices(VoiceChangerFunction callback) {
for (int i = 0; i < mNumOfVoices; i++) {
callback(mVoices[i]);
}
}
static void SetValue(Voice &voice, unsigned int value) {
voice.mValue = value;
std::cout << voice.mValue << std::endl;
}
private:
static const int mNumOfVoices = 4;
Voice mVoices[mNumOfVoices];
};
int main()
{
VoiceManager voiceManager;
VoiceManager::VoiceChangerFunction callback;
callback = std::bind(&VoiceManager::SetValue, std::placeholders::_1, 100);
voiceManager.UpdateVoices(callback);
}
Basically, I create a VoiceChangerFunction function (object) that takes a Voice & as first parameter and returns void.
Later, I bind a function that will take as first parameter the one I'll give to it when I call it, and another parameter that I give when I bind it (100, in my example).
Right?
What I don't understand is: then, this function is passed to UpdateVoices(), which take as input a function/object that has 1 param (Voice &), not 2 as created in my bind function (Voice &, unsigned int).
How can it works?
Its like to have void VoiceChangerFunction(Voice &voice) and call VoiceChangerFunction(Voice &voice, unsigned int value ).
The function prototype is different. I mean: the callback bind I created isn't a VoiceChangerFunctions function, because it takes more parameters.
How can it works/match?
That is exactly the beauty of bind and std::function at works. You are defining the callback as function taking one argument, and bind is returning a function object which takes one argument.
The main point here is that it actually calls the function which takes 2 parameters, but the second one is fixed, and will always be 100 (in your case). This is the sole purpose of binders - to provide a way to call functions with different set of arguments with some fixed values. If you would be calling the function taking the same set of arguments, there would be no reason to use binders at all!
Knowing that bind is similar to lambdas, the same code could be written as - and probably be more clear:
VoiceManager::VoiceChangerFunction callback;
callback = [](Voice& v) { VoiceManager::SetValue(v, 100); };
voiceManager.UpdateVoices(callback);
And if you are curious how it works, you might try to create a binder framework yourself. If you are only doing it for educational purposes and not worried about too many details, it is not that hard.
When you bind, you're making a new function that only takes Voice as a param, that's why it works.
void a_func(int x) { return; }
std::function<void(void)> new_func = std::bind(&a_func, 1);
new_func now has the signature of void(void), so you could pass it around to anywhere that expects a function of type void(void).
When you call new_func, it really calls a_func(1).
Your assumption about bind is wrong.
Your bind call returns a function object that will accept one parameter, namely the placeholder. The other parameter on your function is already bound to 100.
A little example:
void foo(int i1, int i2) {};
std::function<void(int,int)> fn1 = std::bind(foo, std::placeholders::_1, std::placeholders::_2);
std::function<void(int)> fn1 = std::bind(foo, std::placeholders::_1, 1);
std::function<void()> fn1 = std::bind(foo, 1, 1);
The bind will create a matching function depending on bound and unbound parameters.
Update
The compiler will generate a struct from the bind expression and a copy of your parameter. Simplified something like this(this will not compile):
struct Function_{
void(*fn)(Voice &, unsigned int)
unsigned int i_;
Function_(void(*f)(Voice &, unsigned int), unsigned int i):fn(f),i_(i){}
void operator()(Voice& v){
fn(v, i_);
}
}
fn is the first parameter which is a function pointer and the bound (100) is the second. Then all you need is some type erasure and your own bind is ready to go.

How do I Pass a Member Function to a Function as a Function Pointer?

Source of Problem https://github.com/claydonkey/PointerToMember/tree/master
Although touched on in How Can I Pass a Member Function to a Function Pointer?, I feel somewhat dissatisfied with the solutions provided, as I don't want to introduce a dependency on the Boost library.
Comparing std::function for member functions is a post that gets close to a solution but ultimately is less optimistic about the use of std::function in .
(it seems that member functions cannot be passed as function pointers)
The Problem:
A function simpleFunction which cannot be altered takes a callback pfunc:
typedef int (*FuncPtr_t)(void*, std::pair<int,int>&);
static int simpleFunction(FuncPtr_t pfunc, void *context, std::pair<int,int>& nos)
{
pfunc(context, nos);
}
This function is intended to callback the method memberFunction in class SimpleClass:
NB removed void from original post as it better represents a real world usage.* was int memberFunction(void*, std::pair<int,int>& nos)
class SimpleClass {
public:
int memberFunction(std::pair<int,int>& nos) { return nos.first + nos.second; }
};
I expected the following to work:
MemFuncPtr_t MemFunction = &SimpleClass::memberFunction;
simpleFunction(obj.*MemFunction, nos);
but obj.*MemFunction has a type: int (SimpleClass::)(std::pair<int,int>&)
and it needs to be: int (*)(std::pair<int,int>&)
(wheras (obj.*MemFunction) (nos); returns as expected)
I can create and pass a trampoline:
int functionToMemberFunction(void* context, std::pair<int,int> & nos) {
return static_cast<SimpleClass*>(context)->memberFunction(nos);
}
and pass it
simpleFunction(&functionToMemberFunction, &obj, nos);
but it compiles to around 40 instructions.
I can pass a lambda:
simpleFunction((FuncPtr_t)[](void* , std::pair<int,int> & nos) {
return nos.first + nos.second;
}, &obj, nos);
That's surprisingly well optimised but a bit ugly and syntactically cumbersome.
(NB Both and lambdas require C++11)
I can add a static member to SimpleClass:
class SimpleClass {
public:
int memberFunction(void*, std::pair<int,int>& nos) { return nos.first + nos.second; }
static int staticFunction(void*, std::pair<int,int> & nos) { return nos.first + nos.second; }
};
FuncPtr_t StaticMemFunction = &SimpleClass::staticFunction;
and pass it
simpleFunction(StaticMemFunction, nullptr, nos);
and that's just, well ... a static function inside a class.
I can use the <functional> header:
using namespace std::placeholders;
std::function<int(std::pair<int,int>&) > f_simpleFunc =
std::bind(&SimpleClass::memberFunction, obj, _1);
auto ptr_fun = f_simpleFunc.target<int (std::pair<int,int> & ) >();
and try and pass it...
simpleFunction(*ptr_fun, nos);
but ptr_fun reports null.
Looking at the x86 assembly - I am at a loss at how memory is addressed, calling a member function (there are an extra 5 instructions [3 mov, 1 lea and 1 add] over the StaticMemFunction call). I can only imagine that this is down to locating the class instance in memory and then the function within it.
All the suggestions have been useful and I think if I collate them all and return to the original problem, I may have a solution that works for me.
So I thought a solution would be derived from:
simpleFunction(([](void* context,std::pair<int, int> & nos) {
return nos.first + nos.second;
}), &obj, nos);
to become:
simpleFunction(([&](void* context,std::pair<int, int> & nos) {
obj.memberFunction(nos);
}), &obj, nos);
right?
error: cannot convert main()::<lambda(std::pair<int, int>&, void*)> to int (*)(std::pair<int, int>&, void*)
Lambdas that accept closures cannot be cast to a function pointer
The closure type for a lambda-expression with no lambda-capture has a
public non-virtual non-explicit const conversion function to pointer
to function having the same parameter and return types as the closure
type’s function call operator. The value returned by this conversion
function shall be the address of a function that, when invoked, has
the same effect as invoking the closure type’s function call operator.
This makes sense as function pointers carry no state and this is why simpleFunction was gifted with a context pointer void* context (like most callbacks!), which is in turn handled by pFunc- the function pointer. (The context being the SimpleObject instance obj whose member function we wish to delegate to.)
Ergo a good solution seems to be:
solution 1
simpleFunction(([](void* context, std::pair<int,int>& n) {
return static_cast<SimpleClass*>(context)->memberFunction(n);
}), &obj, nos);
NB If obj is moved from local -> global scope the lambda would not require the object to be passed in at all. but that changes the original problem.
Incredibly, if the member-function has no calls to the class within which it resides, it behaves as a static function, the lambda obviating the need for the class instance
solution 2
simpleFunction(([](void* context, std::pair<int,int>& n) {
return static_cast<SimpleClass*>(context)->memberFunction(n);
}), nullptr /* << HERE */, nos); //WILL WORK even though the context is null!
This works perfectly as a solution to the original question: the member function indeed does not rely on anything outside the function scope (is this expected C++ behaviour or a happy hack?).
In conclusion, in trying to compose a simple analogy to a real world problem I have been naive in my the original question and I really want all the functionality of a member-function so solution 1 seems more realistic.
I am little more savvy in distinguishing between member functions and c functions - I spose the clue was in the name member (of a class)
This was all part of a learning experience and the source code including move-semantics solutions is in the link in the original post.
Implement a simple trampoline with a lambda:
#include <iostream>
typedef int (*FuncPtr_t)(void*, int);
static int simpleFunction(FuncPtr_t pfunc, void *context, int nos)
{
return pfunc(context, nos);
}
struct A {
int i;
int pf(int nos) { std::cout << i << " nos = " << nos << "\n"; return i; }
};
int main() {
A a { 1234 };
// could combine the next two lines into one, I didn't.
auto trampoline = [](void *inst, int nos) { return ((A*)inst)->pf(nos); };
simpleFunction(trampoline, &a, 42);
}
http://ideone.com/74Xhes
I've modified it to consider the assembly:
typedef int (*FuncPtr_t)(void*, int);
static int simpleFunction(FuncPtr_t pfunc, void *context, int nos)
{
return pfunc(context, nos);
}
struct A {
int i;
int pf(int nos) { return nos + i; }
};
int f(A& a) {
auto trampoline = [](void *inst, int nos) { return ((A*)inst)->pf(nos); };
return simpleFunction(trampoline, &a, 42);
}
Compiled with -O3 we get:
f(A&):
movl (%rdi), %eax
addl $42, %eax
ret
https://godbolt.org/g/amDKu6
I.e. the compiler is able to eliminate the trampoline entirely.
std::function<> plus lambdas are a nice way to go. Just capture the this in the lambda, an do what you need. You don't event need to write a separate callback if what is being executed is small. Plus std::function is required to not need a heap allocation for lambda that only captures a single pointer.
class A {
std::function <void()> notify;
void someProcessingFunction () {
// do some work
if (notify != nullptr)
notify ();
}
};
class B {
void processNotification () {
// do something in response to notification
}
};
int main ()
{
A a;
B b;
a.notify = [&b] () { b.processNotification (); };
a.someProcessingFunction ();
}
The usual approach is to pass the object as your callback data, as you do in the first example. Any overhead is likely a consequence of the calling convention on your target (or perhaps too low a setting on your compiler's optimiser).
In these circumstances I use a fusion of your first two methods. That is, I create a trampoline, but make it a static function inside the class, to avoid clutter. It does not do what the member function does (as in your second example): it just calls the member function.
Don't worry about a handful of instructions in the calling process. If you ever do need to worry that much about clock cycles, use assembler.

How to call stl::nth_element with a member function inside this class?

I want to use the function nth_element with my own sorting function (which should have access to the data of the object) within a class. Currently, I am doing the following:
class Foo
{
public:
glm::vec3 *points;
int nmbPoints;
bool idxPointCompareX(int a, int b);
void bar();
}
bool Foo::idxPointCompareX(int a, int b)
{return points[a].x < points[b].x;)
void Foo::bar()
{
stl::vector<int> idxPointList;
for(int i = 0; i < nmbPoints; i++) idxPointList.push_back(i);
stl::nth_element(idxPointList.first(),idxPointList.first()+nmbPoints/2,idxPointList.end(), idxPointCompareX);
}
Of course, this did not work and I got the error: "reference to non-static member function must be called". After that, I had a look at Reference to non-static member function must be called, How to initialize std::function with a member-function? and some other questions on here. I understand why this did not work, but I'm unsure how to solve this.
Can someone help me and tell me how to solve this problem?
To take the address of a member function you need to use the correct syntax, i.e. &Foo::idxPointCompareX not just idxPointCompareX
But you also need a Foo object to call the function on, so you would need to bind one to it. Presumably you mean to call it on this so you could use std::bind:
using namespace std::placeholders;
stl::nth_element(begin, begin+n, end,
std::bind(&Foo::idxPointCompareX, this, _1, _2));
Or simpler, use a lambda function:
stl::nth_element(begin, begin+n, end,
[this](int a, int b) { return idxPointCompareX(a, b);}
);
This creates a lambda function that captures this and passes its arguments on to the idxPointCompareX function on the captured this pointer.
idxPointCompareX is a member function, i.e. it cannot be called without some reference to a Foo object. Looking at its definition though, it seems that it doesn't need to be a member since it's purely defined in terms of its arguments.
You could make it a static function (i.e. a "class function") or a free function and then pass that to std::nth_element.
You can't call an object method before it is created, so you have some options here:
Make the method static
Leave the constructor empty and move all into an init method where you call the compare part
Use a lambda
Examples:
Static method:
static bool idxPointCompareX(glm::vec3 a, glm::vec3 b)
{return a.x < b.x;)
Init method:
Foo::bar()
{
stl::vector<int> idxPointList;
for (int i = 0; i < nmbPoints; i++)
idxPointList.push_back(i);
}
Foo::init()
{
stl::nth_element(idxPointList.first(),
idxPointList.first()+nmbPoints/2,idxPointList.end(),
idxPointCompareX);
}
Lambda:
Foo::bar()
{
stl::vector<int> idxPointList;
for (int i = 0; i < nmbPoints; i++)
idxPointList.push_back(i);
stl::nth_element(idxPointList.first(),
idxPointList.first()+nmbPoints/2,idxPointList.end(),
[](int a, int b){return points[a].x < points[b].x;));
}
I would go for the lambda version myself.

Passing "part" of a function pointer as an argument

I'm sure this has been asked before, but it's just hard to search for...
So, what I've got is a function that accepts a function pointer. This function pointer has, say, 3 arguments. So, I want to pass to another function, the same pointer, but with 2 arguments filled in.
So, something like this:
int func1 (int (*funcptr)(int, int, int)) {
return func2(funcptr(,8,9));
}
int func2 (int (*funcptr)(int)) {
return (*funcptr)(2);
}
EDIT:
Ok so I got this now with the usage of a lambda
int func2(int (*funcptr2)(int)) {
return (*funcptr2)(2);
}
int func1(int (*funcptr1)(int, int, int)) {
return func2(
[funcptr1](int i)->int {
return (*funcptr1)(i,8,9);
}
);
}
But it's giving me
"cannot convert func1(int (*)(int, int, int))::<lambda(int)> to int (*)(int) for argument 1 to int func2(int (*)(int))"
This is called a lambda, and you can do it with newer C++ versions, std::bind, boost::bind or boost::function.
To answer your updated question, a lambda which captures variables (as your lambda does with funcptr1) cannot be converted to a function pointer. Intuitively this makes sense since your lambda must store this captured variable per lambda; whereas there is no way to do that with a function pointer.
The best solution is probably to take an argument of type std::function, which is a wrapper for any callable type:
int func2(std::function<int(int)> funcptr2) {
return funcptr2(2);
}
int func1(std::function<int(int,int,int)> funcptr1) {
return func2(
[funcptr1](int i)->int {
return funcptr1(i,8,9);
}
);
}
You can also use templates to make your functions work for any callable type:
template <typename F>
int func2(F funcptr2) {
return funcptr2(2);
}
template <typename F>
int func1(F funcptr1) {
return func2(
[funcptr1](int i)->int {
return funcptr1(i,8,9);
}
);
}
In C, you can't. You would have to pass the function pointer, and the two arguments.
In C++, you can use std::bind (or boost::bind in older versions) to achieve this.