Open bremoran opened 8 years ago
It appears that compiler-polyfill will need some work to enable this. Specifically, it requires an implementation of std::tuple
Not certain if compiler-polyfil is place for library utilities, more like library-polyfill. @pan- already did already some for their ble testing framework. From his commit message `Provide polyfill for:
@0xc0170 I think it might be too early to start doing a lib-polyfill repo. Let's start if off in compiler-polyfill, then break it out into its own repo when necessary.
Added a new set of APIs for C Function escalation.
Suppose there is a C API that looks like this:
typedef void (*foocb) (void*, int, double, char);
int foo(int, char, foocb callback, void * context);
Then, suppose that this should be called in a C++ context, e.g. a lambda. In order to achieve this, the previous commit's static APIs can be used.
Function<void(int,double,char)> foofunc = [](int i, double d, char c) {
printf("%i, %lf, %c\n", i,d,c);
};
foo(1,'a', &foofunc::call_from_void_dec, foofunc.get_ref());
// If the call is to be used multiple times, then:
foo(1,'a', &foofunc::call_from_void, foofunc.get_ref());
Note that get_ref
increments the reference count, so foofunc can even be destroyed. This means that lifetime management is dealt with on behalf of the user.
cc @Patater
I'm not exactly sure what this is supposed to solve, but the idea of doing manual ref counting like this looks quite a bit scary.
@bogdanm https://github.com/ARMmbed/sockets/issues/58
This deals with a very common problem in the C/C++ boundary layer, without the use of CThunk
where it is not required.
@bogdanm Note that this doesn't have to live in Function
. Only the get_ref()
member function needs to exist in Function
. However, since get_ref()
increments the reference count, there probably needs to be a corresponding drop_ref()
The tuple instantiated above is not optimal. It doesn't perform a full sort, so it does not achieve optimal packing.
+1 for having this syntax available Function<void(int,double,char)> foofunc
!
Using similar to std::function, people might try to use it the same way. I did once and failed (use cv qualifier member function with our current fp, see later.) Therefore might be beneficial to share how this differs, or better said what it provides and its known limitations (for a function objects, it's captured nicely in tr1). A quick look at the this changeset a distinction is quite big. For instance, a member function with cv-qualifiers is not covered here.
How are arguments binded? I assume using tuple, first argument plus tuple the rest of arguments? How many arguments can be binded? Is there limitation (FUNCTION_SIZE?)?
Does it allow small object optimization? Looking at the code, seems like not, and we alloc for any member pointer in ctor for Function:
// functional.hpp 112 line
Function(C *o, ReturnType (C::*fp)(ArgTypes...)) {
typedef detail::MemberContainer<C, ReturnType(ArgTypes...)> memberFP;
memberFP * newf = reinterpret_cast<memberFP *>(detail::MemberFPAllocator.alloc());
I am interested to see how call_from_void, and similar work. I'll have a look at this later.
I am missing docs for the hierarchy of classes to build this Function type (where magic lies in), which might answer my questions above.
@0xc0170 You're right, it needs more documentation and more helper methods.
I think it would be a good idea to make sure that all of the std::function
APIs are available on Function
.
The tuple is recursively defined and the only constraint is that it must fit in the available allocator.
Function could replace FunctionPointer. This PR is not quite finished yet, since it requires more documentation. There is also some cleanup that could be done on
bind_first
/bind_last
, which currently take completely different approaches to how they create the newFunction
.Excerpt from the
Function
documentation:In order to maintain compatibility with existing code,
Function
is intended to be duck-type compatible with theFunctionPointer
family of classes, but it is intentionally not named the same way. A family of compatibility classes is provided to support conversion fromFunctionPointer
code toFunction
. These compatibility classes will be deprecated in an upcoming release.Superficially,
Function
is intented to appear similar tostd::function
. However,Function
has a number of key differences.Function
uses reference counting to limit the copying of large callable objects, such as lambdas with large capture lists orFunction
s with large or many arguments.Function
also uses pool allocation so that objects can be created in interrupt context without usingmalloc()
. These choices are to overcome two specific limitations ofstd::function