A short purely technical question:
If I have an uncertain amount of overlapping (time-wise) instances of the class below. Is it and how is it ensured, that the "this" in "call_back_when_done" belongs to the same "this" as it was in "Start"?
class MyClass{
int ident = -1;
bool ready = false;
void Start(string url){
ident = aStaticClass.DoSomethingAndForkThread(url, callback_when_done);
}
void call_back_when_done(){
ready = true;
}
}
e.g.:
for (int i=0; i < 3; i++)
new MyClass().Start(<aURL>);
Thank You
At first, you can bind the function to "this" like described here using currying : (How) is it possible to bind/rebind a method to work with a delegate of a different signature?
I would prefer a lambda function for your example case like described here : C# Lambdas and "this" variable scope
Lambda functions are bound to the scope of the "this" context where they are created. Members of your surrounding Class are automatically visible to the Lambda function. Using a Lambda function you'll get shorter code which can also better optimized by the compiler.
It is guaranteed.
When you pass callback_when_done to DoSomethingAndForkThread in Start, you are not only passing the raw function pointer (like you would in C++ with &MyClass::callback_when_done, but some kind of tuple consisting of the method to call and the object on which the method should be called (this).
If you like it more explicit you can also write a closure manually:
void Start(string url) {
var that = this; // that get's captured by the closure
ident = aStaticClass.DoSomethingAndForkThread(url, () => that.callback_when_done());
}
Related
Still many C++ codes are so difficult for me to understand..
Below is a code snippet from dlib (http://dlib.net file : dlib/external/pybind11/include/pybind11/pybind11.h)
It's a member function definition of class cpp_function and I didn't try to understand the code(no time to do that..that's sad..). I can't understand the syntax in the line I put *** this line! comment at below. I understand the lambda function(unnamed function), so is it assigning a function pointer to rec->impl, the function taking function_call &call as argument and returning handle? So, it looks like defining a function and at the same time assigning the function pointer to a variable. Having asked it, it looks so now.. Please someone confirm this.
void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) {
using namespace detail;
struct capture { remove_reference_t<Func> f; };
...
rec->impl = [](function_call &call) -> handle { // <=== *** this line!
cast_in args_converter;
/* Try to cast the function arguments into the C++ domain */
if (!args_converter.load_args(call))
return PYBIND11_TRY_NEXT_OVERLOAD;
/* Invoke call policy pre-call hook */
process_attributes<Extra...>::precall(call);
/* Get a pointer to the capture object */
auto data = (sizeof(capture) <= sizeof(call.func.data)
? &call.func.data : call.func.data[0]);
capture *cap = const_cast<capture *>(reinterpret_cast<const capture *>(data));
/* Override policy for rvalues -- usually to enforce rvp::move on an rvalue */
const auto policy = return_value_policy_override<Return>::policy(call.func.policy);
/* Function scope guard -- defaults to the compile-to-nothing `void_type` */
using Guard = extract_guard_t<Extra...>;
/* Perform the function call */
handle result = cast_out::cast(
std::move(args_converter).template call<Return, Guard>(cap->f), policy, call.parent);
/* Invoke call policy post-call hook */
process_attributes<Extra...>::postcall(call, result);
return result;
};
...
using FunctionType = Return (*)(Args...);
constexpr bool is_function_ptr =
std::is_convertible<Func, FunctionType>::value &&
sizeof(capture) == sizeof(void *);
if (is_function_ptr) {
rec->is_stateless = true;
rec->data[1] = const_cast<void *>(reinterpret_cast<const void *>(&typeid(FunctionType)));
}
}
rec->impl = [](function_call &call) -> handle
creates a lambda which takes one argument of type function_call and returns a handle, then assigns it to rec->impl.
As lambdas are basically unnamed structs, they also have unnamed types. Since rec->impl obviously exists already and is thus not templatized on the lambda type, the lambda gets converted to some other type during the assignment. (Note: there could however be a templatized and overloaded operator= here)
Typically such types which can take lambdas are either std::function or function pointers as stateless lambdas can be converted to function pointers.
I haven't used C++ in ages. Between what I've forgotten and what has changed in C++ over time, I'm really banging my head against the wall trying to do something that would be trivially easy in JavaScript, or any other language where functions are objects, and not just simple pointers.
I think I understand the basic problem: A class member function only exists in once place in memory (there isn't a different copy of it for each class instance). The only way the function knows what "this" is is because an instance pointer is passed along as an invisible first argument to every function call. A plain-old C-style callback isn't going to know anything about passing that instance pointer.
What I need is a new function that is somehow bound to my class instance, one which knows how to pass "this" along to the member function. That's the function I need to use as a callback.
But I don't know for sure how to dynamically create such a function. I think the code below is on the right track (except for casting pointer types), but it does bother me a bit because it seems like that there'd have to be some dynamic memory allocation going on, and if so, some way to track that allocation and do clean-up later.
class SignalMonitor {
int dataPin;
unsigned short timings[RING_BUFFER_SIZE];
unsigned long lastSignalChange = 0;
int dataIndex = 0;
int syncCount = 0;
void signalHasChanged();
public:
SignalMonitor(int);
};
SignalMonitor::SignalMonitor(int dataPin) {
this->dataPin = dataPin;
function<void()> callback = bind(&SignalMonitor::signalHasChanged, this);
wiringPiISR(dataPin, INT_EDGE_BOTH, callback);
}
void SignalMonitor::signalHasChanged() {
unsigned long now = micros();
int duration = (int) min(now - this->lastSignalChange, 10000ul);
this->lastSignalChange = now;
cout << duration << '\n';
}
I feel like this is close to what I want, but I'm getting this error:
acu-rite-433Mhz-reader.cpp:58:72: error: invalid cast from type ‘std::function<void()>’ to type ‘void*’
wiringPiISR(dataPin, INT_EDGE_BOTH, reinterpret_cast<void *>(callback));
^
Here's the call signature of the function I'm trying to pass this callback to:
int wiringPiISR (int pin, int edgeType, void (*function)(void))
I've found a number of similar issues discussed when searching on this topic, but they either don't quite match what I'm trying to do, or assume much more familiarity with C++ than I currently possess. (All I remember about function pointer types is that they can get hellishly ugly very quickly!)
I tried to use lambda function as a solution, but that led to an error (besides a type mismatch error) about something being "temporary", which I'm assuming meant that the lambda function's scope was temporary.
This is a far from ideal solution (I'm beginning to think there are no ideal solutions here), but it works for me in this particular case where there aren't likely to be very many instances of my SignalMonitor class in use at the same time.
First, I turned my signalHasChanged class method into a static method that takes an instance as an argument. (I could have kept the method as a class method by going through some hairy type-casting, but it wasn't worth it.)
Then I made ten almost-identical indirect callback functions:
void smCallback0() { SignalMonitor::signalHasChanged(monitors[0]); }
void smCallback1() { SignalMonitor::signalHasChanged(monitors[1]); }
void smCallback2() { SignalMonitor::signalHasChanged(monitors[2]); }
void smCallback3() { SignalMonitor::signalHasChanged(monitors[3]); }
void smCallback4() { SignalMonitor::signalHasChanged(monitors[4]); }
void smCallback5() { SignalMonitor::signalHasChanged(monitors[5]); }
void smCallback6() { SignalMonitor::signalHasChanged(monitors[6]); }
void smCallback7() { SignalMonitor::signalHasChanged(monitors[7]); }
void smCallback8() { SignalMonitor::signalHasChanged(monitors[8]); }
void smCallback9() { SignalMonitor::signalHasChanged(monitors[9]); }
Then I stuck all of those functions into an array:
void (*_smCallbacks[MAX_MONITORS])() = {
smCallback0, smCallback1, smCallback2, smCallback3, smCallback4,
smCallback5, smCallback6, smCallback7, smCallback8, smCallback9
};
Along with the monitors array, which is an array of SignalHandler pointers, this gives me ten available callback slots. (_smCallbacks is copied into smCallbacks as a way to get around foreward reference problems.)
The init method for SignalMonitor simply searches for an available slot, plugs itself in, then sets the callback:
void SignalMonitor::init() {
for (int i = 0; i < MAX_MONITORS; ++i) {
if (monitors[i] == NULL) {
callbackIndex = i;
monitors[i] = this;
break;
}
}
if (callbackIndex < 0)
throw "Maximum number of SignalMonitor instances reached";
wiringPiISR(dataPin, INT_EDGE_BOTH, smCallbacks[callbackIndex]);
}
There's also a destructor to free up the callback slots:
SignalMonitor::~SignalMonitor() {
if (callbackIndex >= 0)
monitors[callbackIndex] = NULL;
}
It may help to consider the traditional way of handling a similar issue. Other APIs have been designed where instead of void(*function)(void), wiringPiISR would expect a function void(*function)(void *). This allows the use of
static void signalHasChanged(void *p) {
static_cast<SignalMonitor*>(p)->signalHasChanged();
}
This is not a general solution, but because Raspberry Pi has a limited number of GPIO pins, and you can't have more callback functions than you have pins, you might be able to create one callback function per pin. Then, you need a global data structure that maps the interrupt pin to which SignalMonitor instance (or instances) it should signal. The constructor would register the 'this' object to a specific pin, then set the appropriate callback function based on the pin.
The callback functions would be able to pass a pin argument to a general function, which could then look up the specific SignalMonitor instance and call a class function.
I wouldn't want to do it for 1000 pins, 1000 instances, but this hack should work for anything running on a Pi.
I want to do something like this:
// define a lambda to be called from some class method
auto state_0_stuff = [&](){
.
caller_data.some_func(); <-- identifier undefined compiler error
.
}
// call the lambda from some class method, capturing the data and using in the lambda.
void foo::some_func(){
int state = 0;
bool done = false;
// more data...
bar caller_data;
while(!done){
switch(state){
case 0:
state_0_stuff(); <-- instead of adding lots of code here, call lambda
state = 1;
break;
case 1:
done = true;
break;
}
}
}
This will work if I define the lambda inside the body of foo::some_func, but not if I try to define the lambda outside.
Is there some relatively simple syntax to get this effect?
I don't care if lambdas are used, it was just my first idea. The intent is to simplify the contents of the switch(state) so that the code is more readable than if I add 50 lines of stuff in the case.
Obviously I could use normal functions, and pass a bunch of stuff back and forth, but it would be far less complex if the local state could just be captured by the function, as in Lambda's.
There is no way to implicitly capture objects in a lambda that's outside of the scope of those objects. You need to pass them explicitly.
As a solution, you can add a private member function to foo and call that instead:
void foo::case0(bar& caller_data, /* ... */)
{
lots_of_calcs_that_reference_caller_data();
.
caller_data.some_func();
.
}
void foo::some_func(){
int state = 0;
bool done = false;
// more data...
bar caller_data;
while(!done){
switch(state){
case 0:
case0(caller_data, /* ... */);
state = 1;
break;
case 1:
done = true;
break;
}
}
}
Otherwise you can create a struct with overloaded operator() and pass the "captures" in its constructor.
A lambda captures the state at the point it is declared. So when you have
auto state_0_stuff = [&](){
lots_of_calcs_that_reference_caller_data();
.
caller_data.some_func();
.
}
in the global space [&] will only capture what is available in that space. When you call the lambda in the function it will be using that captured state, not the current state of the function.
You are going to have to either declare the lambda in the function or write a function/functor that you pass the state to. You could also make it a private member function of the class so it will have access to the class state and you would only have to pass any function local state you need to it.
Some more depth on what happens when you declare a lambda:
When you do
auto foo = [&](){ your code here };
The compile expands it into something like (very over simplified):
struct some_compiler_generate_name
{
some_compiler_generate_name(list of captured variables) : initialize captured variables {}
operator () const { your code here }
private:
captured variables;
} foo(list of variables to capture);
So you can see that we create the lambda object right at the point of declaration and since that is done it gets initialized with any captured variables it might have. You can't recapture variables because you can't call its constructor again.
The below given code is taken from LevelDB. I am giving two blocks of code for better understanding. I am unable to understand what is happening.
ThreadState is a structure and I have written here to make it easy for the reader.
struct ThreadState {
int tid; // 0..n-1 when running in n threads
Random rand; // Has different seeds for different threads
Stats stats;
SharedState* shared;
ThreadState(int index)
: tid(index),
rand(1000 + index) {
}
};
Is the marked code below an object instantiation of class Benchmark? What is happening in the marked code below?
void Run() {
PrintHeader();
Open();
const char* benchmarks = FLAGS_benchmarks;
while (benchmarks != NULL) {
{
//code ommitted
}
// Reset parameters that may be overriddden bwlow
***void (Benchmark::*method)(ThreadState*) = NULL;*** // What does this code line mean? // Benchmark is a class.
bool fresh_db = false;
int num_threads = FLAGS_threads;
if (name == Slice("fillseq")) {
fresh_db = true;
method = &Benchmark::WriteSeq;
}
If required, I can give detailed implementation of Benchmark as well.
Thanks a lot for the help!
void (Benchmark::*method)(ThreadState*) = NULL;
// What does this code line mean?
// Benchmark is a class.
The above is a pointer to a member function. Since member functions are not like regular functions (they can only be called on a valid object), you cannot take their address it the same way you would for a free function.
Therefore the above syntax is introduced. It is similar to a regular function pointer except the class specifier Benchmark::. This is essentially the type of the implicit this pointer.
In your case, method is a pointer to a member function that takes ThreadState* as a parameter, and has a void return type. The reason for using it is most probably to simplify the call. First, and based on various parameters, a member function is chosen to be called, and its "address" stored in method. After all the checks are done, there is only a single call to the chosen function via the pointer to member.
Incidentally, &Benchmark::WriteSeq is how the code obtains the "address" of the member function WriteSeq. You must use the address-of operator on the qualified function name.
I've written a function foreach that accepts a lambda function ala:
void foreach(void (*p)(pNode))
{ /* ... */ }
Which works as intended if I pass a lambda function from the main loop:
int a = 5;
env.N().foreach
(
[&](pNode n)->void
{
n->tps(a);
}
);
However, if I try to call the same function from within a member method, the lambda function "inherits" the scope of the member function and generates a compiler error. For example, if I try to include it inside the member method of class Object named method(), I get the following error:
error: no matching function for call to ‘IDSet<Node>::foreach(Object::method()::<lambda(pNode)>)’
note: candidate is: void IDSet<T>::foreach(void (*)(IDSet<T>::pT)) [with T = Node, IDSet<T>::pT = pNode]
I realize this is the compiler being safe, since I could include instance-specific variables inside the lambda function, in which case the lambda would need to be scoped, however I'm wondering if it's possible to make this lambda "static".
I've tried a reinterpret_cast, however that gives me this error:
error: invalid cast from type ‘Object::method()::<lambda(pNode)>’ to type ‘void (*)(pNode)’
Specifying static before [&](pNode ... doesn't seem like valid syntax either.
Desperately, I also tried changing [&] to [=], [], [a], none of which worked.
Does anyone know if there is a way to do accomplish my goal of creating a "static" lambda function, or at any sort of lambda function that will be accepted for that matter?
Thanks!
Answer:
With help from Cat Plus Plus, I was able to turn my incorrect code:
void foreach(void (*p)(pT))
{
for(pTiter i = _map.begin(); i != _map.end(); i++)
{
(*p)(i->second);
}
}
into fully functional code:
void foreach(std::function<void(pT)>(p))
{
for(pTiter i = _map.begin(); i != _map.end(); i++)
{
p(i->second);
}
}
that does what I was looking for perfectly.
Well, you can not use pointers.
void foreach(std::function<void(pNode)>);