I am creating a mechanism which allows users to form arbitrary complex functions from basic building blocks using the decorator pattern. This works fine functionality wise, but I don't like the fact that it involves a lot of virtual calls, particularly when the nesting depth becomes large. It worries me because the complex function may called often (>100.000 times).
To avoid this problem, I tried to turn the decorator scheme into a std::function once it was finished (cfr. to_function() in the SSCCE). All internal function calls are wired during construction of the std::function. I figured this would be faster to evaluate than the original decorator scheme because no virtual lookups need to be performed in the std::function version.
Alas, benchmarks prove me wrong: the decorator scheme is in fact faster than the std::function I built from it. So now I am left wondering why. Maybe my test setup is faulty since I only use two trivial basic functions, which means the vtable lookups may be cached?
The code I used is included below, unfortunately it is quite long.
SSCCE
// sscce.cpp
#include <iostream>
#include <vector>
#include <memory>
#include <functional>
#include <random>
/**
* Base class for Pipeline scheme (implemented via decorators)
*/
class Pipeline {
protected:
std::unique_ptr<Pipeline> wrappee;
Pipeline(std::unique_ptr<Pipeline> wrap)
:wrappee(std::move(wrap)){}
Pipeline():wrappee(nullptr){}
public:
typedef std::function<double(double)> FnSig;
double operator()(double input) const{
if(wrappee.get()) input=wrappee->operator()(input);
return process(input);
}
virtual double process(double input) const=0;
virtual ~Pipeline(){}
// Returns a std::function which contains the entire Pipeline stack.
virtual FnSig to_function() const=0;
};
/**
* CRTP for to_function().
*/
template <class Derived>
class Pipeline_CRTP : public Pipeline{
protected:
Pipeline_CRTP(const Pipeline_CRTP<Derived> &o):Pipeline(o){}
Pipeline_CRTP(std::unique_ptr<Pipeline> wrappee)
:Pipeline(std::move(wrappee)){}
Pipeline_CRTP():Pipeline(){};
public:
typedef typename Pipeline::FnSig FnSig;
FnSig to_function() const override{
if(Pipeline::wrappee.get()!=nullptr){
FnSig wrapfun = Pipeline::wrappee->to_function();
FnSig processfun = std::bind(&Derived::process,
static_cast<const Derived*>(this),
std::placeholders::_1);
FnSig fun = [=](double input){
return processfun(wrapfun(input));
};
return std::move(fun);
}else{
FnSig processfun = std::bind(&Derived::process,
static_cast<const Derived*>(this),
std::placeholders::_1);
FnSig fun = [=](double input){
return processfun(input);
};
return std::move(fun);
}
}
virtual ~Pipeline_CRTP(){}
};
/**
* First concrete derived class: simple scaling.
*/
class Scale: public Pipeline_CRTP<Scale>{
private:
double scale_;
public:
Scale(std::unique_ptr<Pipeline> wrap, double scale) // todo move
:Pipeline_CRTP<Scale>(std::move(wrap)),scale_(scale){}
Scale(double scale):Pipeline_CRTP<Scale>(),scale_(scale){}
double process(double input) const override{
return input*scale_;
}
};
/**
* Second concrete derived class: offset.
*/
class Offset: public Pipeline_CRTP<Offset>{
private:
double offset_;
public:
Offset(std::unique_ptr<Pipeline> wrap, double offset) // todo move
:Pipeline_CRTP<Offset>(std::move(wrap)),offset_(offset){}
Offset(double offset):Pipeline_CRTP<Offset>(),offset_(offset){}
double process(double input) const override{
return input+offset_;
}
};
int main(){
// used to make a random function / arguments
// to prevent gcc from being overly clever
std::default_random_engine generator;
auto randint = std::bind(std::uniform_int_distribution<int>(0,1),std::ref(generator));
auto randdouble = std::bind(std::normal_distribution<double>(0.0,1.0),std::ref(generator));
// make a complex Pipeline
std::unique_ptr<Pipeline> pipe(new Scale(randdouble()));
for(unsigned i=0;i<100;++i){
if(randint()) pipe=std::move(std::unique_ptr<Pipeline>(new Scale(std::move(pipe),randdouble())));
else pipe=std::move(std::unique_ptr<Pipeline>(new Offset(std::move(pipe),randdouble())));
}
// make a std::function from pipe
Pipeline::FnSig fun(pipe->to_function());
double bla=0.0;
for(unsigned i=0; i<100000; ++i){
#ifdef USE_FUNCTION
// takes 110 ms on average
bla+=fun(bla);
#else
// takes 60 ms on average
bla+=pipe->operator()(bla);
#endif
}
std::cout << bla << std::endl;
}
Benchmark
Using pipe:
g++ -std=gnu++11 sscce.cpp -march=native -O3
sudo nice -3 /usr/bin/time ./a.out
-> 60 ms
Using fun:
g++ -DUSE_FUNCTION -std=gnu++11 sscce.cpp -march=native -O3
sudo nice -3 /usr/bin/time ./a.out
-> 110 ms
You have std::functions binding lambdas that call std::functions that bind lamdbas that call std::functions that ...
Look at your to_function. It creates a lambda that calls two std::functions, and returns that lambda bound into another std::function. The compiler won't resolve any of these statically.
So in the end, you end with with just as many indirect calls as the virtual function solution, and that's if you get rid of the bound processfun and directly call it in the lambda. Otherwise you have twice as many.
If you want a speedup, you will have to create the entire pipeline in a way that can be statically resolved, and that means a lot more templates before you can finally erase the type into a single std::function.
As Sebastian Redl's answer says, your "alternative" to virtual functions adds several layers of indirection through dynamically bound functions (either virtual, or through function pointers, depending on the std::function implementation) and then it still calls the virtual Pipeline::process(double) function anyway!
This modification makes it significantly faster, by removing one layer of std::function indirection and preventing the call to Derived::process being virtual:
FnSig to_function() const override {
FnSig fun;
auto derived_this = static_cast<const Derived*>(this);
if (Pipeline::wrappee) {
FnSig wrapfun = Pipeline::wrappee->to_function();
fun = [=](double input){
return derived_this->Derived::process(wrapfun(input));
};
} else {
fun = [=](double input){
return derived_this->Derived::process(input);
};
}
return fun;
}
There's still more work being done here than in the virtual function version though.
std::function is notoriously slow; type erasure and the resulting allocation play a part in this, also, with gcc, invocations are inlined/optimized badly. For this reason there exist a plethora of C++ "delegates" with which people attempt to resolve this problem. I ported one to Code Review:
https://codereview.stackexchange.com/questions/14730/impossibly-fast-delegate-in-c11
But you can find plenty of others with Google, or write your own.
EDIT:
These days, look here for a fast delegate.
libstdc++ implementation of std::function works roughly as follows:
template<typename Signature>
struct Function
{
Ptr functor;
Ptr functor_manager;
template<class Functor>
Function(const Functor& f)
{
functor_manager = &FunctorManager<Functor>::manage;
functor = new Functor(f);
}
Function(const Function& that)
{
functor = functor_manager(CLONE, that->functor);
}
R operator()(args) // Signature
{
return functor_manager(INVOKE, functor, args);
}
~Function()
{
functor_manager(DESTROY, functor);
}
}
template<class Functor>
struct FunctorManager
{
static manage(int operation, Functor& f)
{
switch (operation)
{
case CLONE: call Functor copy constructor;
case INVOKE: call Functor::operator();
case DESTROY: call Functor destructor;
}
}
}
So although std::function doesn't know the exact type of the Functor object, it dispatches the important operations through a functor_manager function pointer that is a static function of a template instance that does know about the Functor type.
Each std::function instance will allocate on the heap its own owned copy of the functor object (unless it is not larger than a pointer, such as a function pointer, in which case it just holds the pointer as a subobject).
The important take away is that copying of std::function is expensive if the underlying functor object has an expensive copy constructor and/or takes lots of space (for example to hold bound parameters).
Related
This code is just for illustrating the question.
#include <functional>
struct MyCallBack {
void Fire() {
}
};
int main()
{
MyCallBack cb;
std::function<void(void)> func = std::bind(&MyCallBack::Fire, &cb);
}
Experiments with valgrind shows that the line assigning to func dynamically allocates about 24 bytes with gcc 7.1.1 on linux.
In the real code, I have a few handfuls of different structs all with a void(void) member function that gets stored in ~10 million std::function<void(void)>.
Is there any way I can avoid memory being dynamically allocated when doing std::function<void(void)> func = std::bind(&MyCallBack::Fire, &cb); ? (Or otherwise assigning these member function to a std::function)
Unfortunately, allocators for std::function has been dropped in C++17.
Now the accepted solution to avoid dynamic allocations inside std::function is to use lambdas instead of std::bind. That does work, at least in GCC - it has enough static space to store the lambda in your case, but not enough space to store the binder object.
std::function<void()> func = [&cb]{ cb.Fire(); };
// sizeof lambda is sizeof(MyCallBack*), which is small enough
As a general rule, with most implementations, and with a lambda which captures only a single pointer (or a reference), you will avoid dynamic allocations inside std::function with this technique (it is also generally better approach as other answer suggests).
Keep in mind, for that to work you need guarantee that this lambda will outlive the std::function. Obviously, it is not always possible, and sometime you have to capture state by (large) copy. If that happens, there is no way currently to eliminate dynamic allocations in functions, other than tinker with STL yourself (obviously, not recommended in general case, but could be done in some specific cases).
As an addendum to the already existent and correct answer, consider the following:
MyCallBack cb;
std::cerr << sizeof(std::bind(&MyCallBack::Fire, &cb)) << "\n";
auto a = [&] { cb.Fire(); };
std::cerr << sizeof(a);
This program prints 24 and 8 for me, with both gcc and clang. I don't exactly know what bind is doing here (my understanding is that it's a fantastically complicated beast), but as you can see, it's almost absurdly inefficient here compared to a lambda.
As it happens, std::function is guaranteed to not allocate if constructed from a function pointer, which is also one word in size. So constructing a std::function from this kind of lambda, which only needs to capture a pointer to an object and should also be one word, should in practice never allocate.
Run this little hack and it probably will print the amount of bytes you can capture without allocating memory:
#include <iostream>
#include <functional>
#include <cstring>
void h(std::function<void(void*)>&& f, void* g)
{
f(g);
}
template<size_t number_of_size_t>
void do_test()
{
size_t a[number_of_size_t];
std::memset(a, 0, sizeof(a));
a[0] = sizeof(a);
std::function<void(void*)> g = [a](void* ptr) {
if (&a != ptr)
std::cout << "malloc was called when capturing " << a[0] << " bytes." << std::endl;
else
std::cout << "No allocation took place when capturing " << a[0] << " bytes." << std::endl;
};
h(std::move(g), &g);
}
int main()
{
do_test<1>();
do_test<2>();
do_test<3>();
do_test<4>();
}
With gcc version 8.3.0 this prints
No allocation took place when capturing 8 bytes.
No allocation took place when capturing 16 bytes.
malloc was called when capturing 24 bytes.
malloc was called when capturing 32 bytes.
Many std::function implementations will avoid allocations and use space inside the function class itself rather than allocating if the callback it wraps is "small enough" and has trivial copying. However, the standard does not require this, only suggests it.
On g++, a non-trivial copy constructor on a function object, or data exceeding 16 bytes, is enough to cause it to allocate. But if your function object has no data and uses the builtin copy constructor, then std::function won't allocate.
Also, if you use a function pointer or a member function pointer, it won't allocate.
While not directly part of your question, it is part of your example.
Do not use std::bind. In virtually every case, a lambda is better: smaller, better inlining, can avoid allocations, better error messages, faster compiles, the list goes on. If you want to avoid allocations, you must also avoid bind.
I propose a custom class for your specific usage.
While it's true that you shouldn't try to re-implement existing library functionality because the library ones will be much more tested and optimized, it's also true that it applies for the general case. If you have a particular situation like in your example and the standard implementation doesn't suite your needs you can explore implementing a version tailored to your specific use case, which you can measure and tweak as necessary.
So I have created a class akin to std::function<void (void)> that works only for methods and has all the storage in place (no dynamic allocations).
I have lovingly called it Trigger (inspired by your Fire method name). Please do give it a more suited name if you want to.
// helper alias for method
// can be used in user code
template <class T>
using Trigger_method = auto (T::*)() -> void;
namespace detail
{
// Polymorphic classes needed for type erasure
struct Trigger_base
{
virtual ~Trigger_base() noexcept = default;
virtual auto placement_clone(void* buffer) const noexcept -> Trigger_base* = 0;
virtual auto call() -> void = 0;
};
template <class T>
struct Trigger_actual : Trigger_base
{
T& obj;
Trigger_method<T> method;
Trigger_actual(T& obj, Trigger_method<T> method) noexcept : obj{obj}, method{method}
{
}
auto placement_clone(void* buffer) const noexcept -> Trigger_base* override
{
return new (buffer) Trigger_actual{obj, method};
}
auto call() -> void override
{
return (obj.*method)();
}
};
// in Trigger (bellow) we need to allocate enough storage
// for any Trigger_actual template instantiation
// since all templates basically contain 2 pointers
// we assume (and test it with static_asserts)
// that all will have the same size
// we will use Trigger_actual<Trigger_test_size>
// to determine the size of all Trigger_actual templates
struct Trigger_test_size {};
}
struct Trigger
{
std::aligned_storage_t<sizeof(detail::Trigger_actual<detail::Trigger_test_size>)>
trigger_actual_storage_;
// vital. We cannot just cast `&trigger_actual_storage_` to `Trigger_base*`
// because there is no guarantee by the standard that
// the base pointer will point to the start of the derived object
// so we need to store separately the base pointer
detail::Trigger_base* base_ptr = nullptr;
template <class X>
Trigger(X& x, Trigger_method<X> method) noexcept
{
static_assert(sizeof(trigger_actual_storage_) >=
sizeof(detail::Trigger_actual<X>));
static_assert(alignof(decltype(trigger_actual_storage_)) %
alignof(detail::Trigger_actual<X>) == 0);
base_ptr = new (&trigger_actual_storage_) detail::Trigger_actual<X>{x, method};
}
Trigger(const Trigger& other) noexcept
{
if (other.base_ptr)
{
base_ptr = other.base_ptr->placement_clone(&trigger_actual_storage_);
}
}
auto operator=(const Trigger& other) noexcept -> Trigger&
{
destroy_actual();
if (other.base_ptr)
{
base_ptr = other.base_ptr->placement_clone(&trigger_actual_storage_);
}
return *this;
}
~Trigger() noexcept
{
destroy_actual();
}
auto destroy_actual() noexcept -> void
{
if (base_ptr)
{
base_ptr->~Trigger_base();
base_ptr = nullptr;
}
}
auto operator()() const
{
if (!base_ptr)
{
// deal with this situation (error or just ignore and return)
}
base_ptr->call();
}
};
Usage:
struct X
{
auto foo() -> void;
};
auto test()
{
X x;
Trigger f{x, &X::foo};
f();
}
Warning: only tested for compilation errors.
You need to thoroughly test it for correctness.
You need to profile it and see if it has a better performance than other solutions. The advantage of this is because it's in house cooked you can make tweaks to the implementation to increase performance on your specific scenarios.
As #Quuxplusone mentioned in their answer-as-a-comment, you can use inplace_function here. Include the header in your project, and then use like this:
#include "inplace_function.h"
struct big { char foo[20]; };
static stdext::inplace_function<void(), 8> inplacefunc;
static std::function<void()> stdfunc;
int main() {
static_assert(sizeof(inplacefunc) == 16);
static_assert(sizeof(stdfunc) == 32);
inplacefunc = []() {};
// fine
struct big a;
inplacefunc = [a]() {};
// test.cpp:15:24: required from here
// inplace_function.h:237:33: error: static assertion failed: inplace_function cannot be constructed from object with this (large) size
// 237 | static_assert(sizeof(C) <= Capacity,
// | ~~~~~~~~~~^~~~~~~~~~~
// inplace_function.h:237:33: note: the comparison reduces to ‘(20 <= 8)’
}
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.
I'm having issues with getting a partially-qualified function object to call later, with variable arguments, in another thread.
In GCC, I've been using a macro and typedef I made but I'm finishing up my project an trying to clear up warnings.
#define Function_Cast(func_ref) (SubscriptionFunction*) func_ref
typedef void(SubscriptionFunction(void*, std::shared_ptr<void>));
Using the Function_Cast macro like below results in "warning: casting between pointer-to-function and pointer-to-object is conditionally-supported"
Subscriber* init_subscriber = new Subscriber(this, Function_Cast(&BaseLoaderStaticInit::init), false);
All I really need is a pointer that I can make a std::bind<function_type> object of. How is this usually done?
Also, this conditionally-supported thing is really annoying. I know that on x86 my code will work fine and I'm aware of the limitations of relying on that sizeof(void*) == sizeof(this*) for all this*.
Also, is there a way to make clang treat function pointers like data pointers so that my code will compile? I'm interested to see how bad it fails (if it does).
Relevant Code:
#define Function_Cast(func_ref) (SubscriptionFunction*) func_ref
typedef void(SubscriptionFunction(void*, std::shared_ptr<void>));
typedef void(CallTypeFunction(std::shared_ptr<void>));
Subscriber(void* owner, SubscriptionFunction* func, bool serialized = true) {
this->_owner = owner;
this->_serialized = serialized;
this->method = func;
call = std::bind(&Subscriber::_std_call, this, std::placeholders::_1);
}
void _std_call(std::shared_ptr<void> arg) { method(_owner, arg); }
The problem here is that you are trying to use a member-function pointer in place of a function pointer, because you know that, under-the-hood, it is often implemented as function(this, ...).
struct S {
void f() {}
};
using fn_ptr = void(*)(S*);
void call(S* s, fn_ptr fn)
{
fn(s);
delete s;
}
int main() {
call(new S, (fn_ptr)&S::f);
}
http://ideone.com/fork/LJiohQ
But there's no guarantee this will actually work and obvious cases (virtual functions) where it probably won't.
Member functions are intended to be passed like this:
void call(S* s, void (S::*fn)())
and invoked like this:
(s->*fn)();
http://ideone.com/bJU5lx
How people work around this when they want to support different types is to use a trampoline, which is a non-member function. You can do this with either a static [member] function or a lambda:
auto sub = new Subscriber(this, [](auto* s){ s->init(); });
or if you'd like type safety at your call site, a templated constructor:
template<typename T>
Subscriber(T* t, void(T::*fn)(), bool x);
http://ideone.com/lECOp6
If your Subscriber constructor takes a std::function<void(void))> rather than a function pointer you can pass a capturing lambda and eliminate the need to take a void*:
new Subscriber([this](){ init(); }, false);
it's normally done something like this:
#include <functional>
#include <memory>
struct subscription
{
// RAII unsubscribe stuff in destructor here....
};
struct subscribable
{
subscription subscribe(std::function<void()> closure, std::weak_ptr<void> sentinel)
{
// perform the subscription
return subscription {
// some id so you can unsubscribe;
};
}
//
//
void notify_subscriber(std::function<void()> const& closure,
std::weak_ptr<void> const & sentinel)
{
if (auto locked = sentinel.lock())
{
closure();
}
}
};
So, I have the following situation:
I'm coding for the mbed online compliler, on a low-memory microcontroller.
Real Time performance is very important, I want this to take less than a microsecond. 10 microseconds would be tolerable.
I'm using their timeout library, which provides an API for calling an ISR after a specified time, but requires that the ISR be a void/void function. (including a member function.
void TimeoutCallback(void) { do stuff that I want to do on timeout.} // ISR
Timeout to;
to.attach_us(&TimeoutCallback, 750) // Call TimeoutCallback in 750 us.
I created a vector of Timeout objects, which all get set at once, to the same function, with a different amount of time. I want to somehow pass into the TimeoutCallback which Timeout object called it.
My initial thought was to overload the Timeout class to allow it to accept int function(int) function pointers, and to accept a number in the overloaded attach function that gets passed to said function pointer. However, I'm unsure whether this is actually practical given the messy (and device-specific) inheritance of the Timeout class.
Now, I wonder whether there is a way to programatically create a void/void function that wraps a void/int function, and included a changeable reference int which is passed to the wrapped function.
While Tony D's solution is appropriate if using the mbed Ticker class, there is an alternative method using the mbed RtosTimer.
The RtosTimer constructor takes a void* argument that is passed to the handler on timeout. The handler has the signature:
void handler(void const* n)
Where n is the pointer argument passed to the constructor and can be used to ID the specific timeout.
Unlike Ticker where the timeout function runs in the interrupt context, for RtosTimer the handler runs as a thread, so gives greater flexibility, but potentially greater latency.
As your library can call member functions, you can create an adapter ala...
template <typename Func, Func func>
struct Adapter
{
Adapter(int n) : n_(n) { }
void f() { func(n_); }
int n_;
};
To use it:
Adapter<void(*)(int), My_Function_Expecting_An_Int> adapter(the_int);
to.attach_us(&adapter, &decltype(adapter)::f, timeout_us);
Make sure the adapter's lifetime lasts until the callback....
To call a member function:
#include <iostream>
#include <string>
#include <vector>
struct MyObj
{
void f(int n) { std::cout <<"hi " << n << "\n"; }
};
template <typename Class, typename PFunc>
struct Adapter
{
Adapter(Class& object, PFunc pFunc, int n) : object_(object), pFunc_(pFunc), n_(n) { }
void f() { (object_.*pFunc_)(n_); }
Class& object_;
PFunc pFunc_;
int n_;
};
int main()
{
MyObj myObj;
Adapter<MyObj, void(MyObj::*)(int)> adapter(myObj, &MyObj::f, 43);
adapter.f();
}
I just got burned by a bug that is partially due to my lack of understanding, and partially due to what I think is suboptimal design in our codebase. I'm curious as to how my 5-minute solution can be improved.
We're using ref-counted objects, where we have AddRef() and Release() on objects of these classes. One particular object is derived from the ref-count object, but a common function to get an instance of these objects (GetExisting) hides an AddRef() within itself without advertising that it is doing so. This necessitates doing a Release at the end of the functional block to free the hidden ref, but a developer who didn't inspect the implementation of GetExisting() wouldn't know that, and someone who forgets to add a Release at the end of the function (say, during a mad dash of bug-fixing crunch time) leaks objects. This, of course, was my burn.
void SomeFunction(ProgramStateInfo *P)
{
ThreadClass *thread = ThreadClass::GetExisting( P );
// some code goes here
bool result = UseThreadSomehow(thread);
// some code goes here
thread->Release(); // Need to do this because GetExisting() calls AddRef()
}
So I wrote up a little class to avoid the need for the Release() at the end of these functions.
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
ThreadClass * Thread() const { return m_T; }
};
So that now I can just do this:
void SomeFunction(ProgramStateInfo *P)
{
ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
// some code goes here
bool result = UseThreadSomehow(ThreadC.Thread());
// some code goes here
// Automagic Release() in ThreadC Destructor!!!
}
What I don't like is that to access the thread pointer, I have to call a member function of ThreadContainer, Thread(). Is there some clever way that I can clean that up so that it's syntactically prettier, or would anything like that obscure the meaning of the container and introduce new problems for developers unfamiliar with the code?
Thanks.
use boost::shared_ptr
it is possible to define your own destructor function, such us in next example: http://www.boost.org/doc/libs/1_38_0/libs/smart_ptr/sp_techniques.html#com
Yes, you can implement operator ->() for the class, which will recursively call operator ->() on whatever you return:
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
ThreadClass * operator -> () const { return m_T; }
};
It's effectively using smart pointer semantics for your wrapper class:
Thread *t = new Thread();
...
ThreadContainer tc(t);
...
tc->SomeThreadFunction(); // invokes tc->t->SomeThreadFunction() behind the scenes...
You could also write a conversion function to enable your UseThreadSomehow(ThreadContainer tc) type calls in a similar way.
If Boost is an option, I think you can set up a shared_ptr to act as a smart reference as well.
Take a look at ScopeGuard. It allows syntax like this (shamelessly stolen from that link):
{
FILE* topSecret = fopen("cia.txt");
ON_BLOCK_EXIT(std::fclose, topSecret);
... use topSecret ...
} // topSecret automagically closed
Or you could try Boost::ScopeExit:
void World::addPerson(Person const& aPerson) {
bool commit = false;
m_persons.push_back(aPerson); // (1) direct action
BOOST_SCOPE_EXIT( (&commit)(&m_persons) )
{
if(!commit)
m_persons.pop_back(); // (2) rollback action
} BOOST_SCOPE_EXIT_END
// ... // (3) other operations
commit = true; // (4) turn all rollback actions into no-op
}
I would recommend following bb advice and using boost::shared_ptr<>. If boost is not an option, you can take a look at std::auto_ptr<>, which is simple and probably addresses most of your needs. Take into consideration that the std::auto_ptr has special move semantics that you probably don't want to mimic.
The approach is providing both the * and -> operators together with a getter (for the raw pointer) and a release operation in case you want to release control of the inner object.
You can add an automatic type-cast operator to return your raw pointer. This approach is used by Microsoft's CString class to give easy access to the underlying character buffer, and I've always found it handy. There might be some unpleasant surprises to be discovered with this method, as in any time you have an implicit conversion, but I haven't run across any.
class ThreadContainer
{
private:
ThreadClass *m_T;
public:
ThreadContainer(Thread *T){ m_T = T; }
~ThreadContainer() { if(m_T) m_T->Release(); }
operator ThreadClass *() const { return m_T; }
};
void SomeFunction(ProgramStateInfo *P)
{
ThreadContainer ThreadC(ThreadClass::GetExisting( P ));
// some code goes here
bool result = UseThreadSomehow(ThreadC);
// some code goes here
// Automagic Release() in ThreadC Destructor!!!
}