Skip to content
This repository has been archived by the owner on Jan 15, 2021. It is now read-only.

FunctionPointer and FunctionPointerBind improvements #39

Open
pan- opened this issue Oct 26, 2015 · 3 comments
Open

FunctionPointer and FunctionPointerBind improvements #39

pan- opened this issue Oct 26, 2015 · 3 comments
Labels

Comments

@pan-
Copy link
Member

pan- commented Oct 26, 2015

Several improvements can be made on FunctionPointer and FunctionPointerBind classes. While all of them may not be applicable, I will list everything that is on my mind for this subject.

Unique name for all FunctionPointerX classes:

Today, the FunctionPointer class add the arity of the function to the class suffix name (FunctionPointer0, FunctionPointer1, ..., FunctionPointerN). It is possible to to use a single class name across all FunctionPointer if the "function signature type" is used instead of a list of Return + Arguments type list in template parameters.

template<typename FunctionType>
class FunctionPointer;

template<typename ReturnType>
class FunctionPointer<ReturnType()> {
// implementation
};

template<typename ReturnType, typename Arg1>
class FunctionPointer<ReturnType(Arg1)> {
// implementation
};

// another strategy is to inherit publicly from the actual implementation and add the forwarding constructors

This little change might just look like a cosmetic one, it's not:

  • It allow the user to use the syntax of std::function<>
  • It allow the usage FunctionPointer class in genric/meta programming code
  • If one day we switch to cpp11, it will allow the rewrite of FunctionPointer class with variadic templates without breaking client code.

Clarification of FunctionPointer semantic

The semantic of FunctionPointer, FunctionPointerBind and FunctionPointer is not clear. Is it a polymorphic type ? Is it a value type ?

If it is a value type :

  • The equality operator should be fixed:
FunctionPointer<int, int> foo(fooPtr, &Foo::fooMethod);
FunctionBind<int> bar(foo.bind(42));

assert(foo != bar);      // right now, foo and bar are considered equals
  • FunctionPointer and FunctionPointerBind, should not be "related", we can still reuse code from FunctionPointerBase by using private inheritance instead of public inheritance. It will also allow to remove all virtual statements.
  • copy constructor and copy operator should be added to FunctionPointer class
  • Equality operator should be added to FunctionPointer and FunctionPointerBase

If it is a true polymorphic type:

  • The main operation (calling a function) should be public and available through pointers or references to FunctionPointerBase .

FunctionPointer and FunctionPointerBind should handle function objects

At the moment, it is not possible to handle function object values with FunctionPointer. This addition will be required to support c++11 lambda.

FunctionPointer does not handle smart pointers

It would be nice if FunctionPointer can handle smart pointers (for RAII purposes).

FunctionPointer<void> makeBar() {
    SharedPtr<Foo> fooPtr(new Foo);
    FunctionPointer<void> bar(fooPtr, &Foo::someMethod);
    // the returned object will still be valid and their will be no memory leaks 
    return bar;
}

FunctionPointer and FunctionPointerBind takes too much space:

It is possible to reduce the size of FunctionPointer and FunctionPointerBind by optimizing the pointer to member function storage.

    struct MemberFunctionAndPtr_t {
        /*
         * forward declaration of a class and a member function to this class. 
         * Because the compiler doesn't know anything about the forwarded member 
         * function, it will always use the biggest size and the biggest alignment 
         * that a member function can take for objects of type UndefinedMemberFunction.
         */
        class UndefinedClass;
        typedef void (UndefinedClass::*UndefinedMemberFunction)(void*);

        void* _object;
        union {
            char _memberFunction[sizeof(UndefinedMemberFunction)];
            UndefinedMemberFunction _alignment;            
        };
    };

    union {
        Function_t                         _function;                      /**< static function pointer  */ 
        MemberFunctionAndPtr_t _memberFunctionAndPointer;      
    };

It is also possible to reduce the size of bound arguments if we use a well tuned generic Tuple type instead of a POD as bound arguments storage. A well optimized Tuple type can reorganized its member at compile time and reduce padding.

struct { 
    char foo;
    int bar;
} POD_t

// will take 8 bytes
POD_t foo;

// will take 5 bytes
Tuple<char, int> bar;
@rainierwolfcastle
Copy link

ARM Internal Ref: IOTSFW-1087

@bremoran
Copy link
Contributor

This all looks really good to me. I'd be happy to see these optimizations added!

I'm not sure what the right semantics are for comparing function pointers. I'm not convinced that it's necessarily wrong to compare a function pointer to a function pointer with bound arguments and discover they are equal if they both point to the same underlying function pointer.

On the other hand, this is not likely to be the behaviour that a developer expects. It might be reasonable to argue that a comparison of FunctionPointer to FunctionPointerBind should always fail.

@dbaba
Copy link

dbaba commented May 16, 2016

FunctionPointer and FunctionPointerBind should handle function objects

I need this support in order to use lambda. Because of -fno-rtii option in yotta_targets/mbed-gcc/CMake/toolchain.make, I don't have any way to convert std::function, which is a lambda function type, to c-style function pointer which FunctionPointers' constructors require.

Of course, -fno-rtii makes sense for mbed OS apps so I think FunctionPointer/FunctionPointerBind should support the feature.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants