Code like this:
int code = pthread_create(&d->thread_id, &attr, QThreadPrivate::start, this);
which QThreadPrivate::start is a static function.
So,what use is the fourth parameter this? And what is the difference if this is replaced by NULL?
This is a common idiom. You want to start a thread, but you want that thread to operate on a specific object. So you need to pass the thread a pointer to the object you want it to operate on. If you're within a member function for that object, the this pointer points to the object you're operating on. You can't pass a pointer to a member function directly (because the type would be different), so you use a static member function whose sole purpose is to cast the this pointer back to the correct type and run a non-static member function.
If you changed this to NULL, the thread would have no idea what object it was supposed to operate on. Likely, QThreadPrivate::start would fault or fail, since it would be unable to invoke a non-static member function on the instance without a pointer to that instance.
Say you have a class that has a normal member function that takes no parameters and returns no parameters. You have some code that has no idea about your class or any of its structures. You want to give that code enough information to call that member function on a particular class instance. What do you pass it? You can't pass it a pointer to the member function because with no idea about your class, it can't call a normal class member function. Answer: You pass it a pointer to a static member function whose implementation calls the normal member function, and you pass it a pointer to the instance whose method you want it to invoke.
The fourth parameter of pthread_create is passed untouched to the thread function and allows that function to change behaviour based on that argument.
OpenGroup documentation for pthread_create, detailing this, can be found here.
In this case, it's simply passing the pointer to the current object, presumably so that the start function can use that to access member variables for the specific object.
If you pass NULL instead, the created thread will get NULL and won't be able to access object specific data (without crashing and burning badly with a null pointer dereference).
You may think that, because QThreadPrivate::start is a static function, it wouldn't be able to access non-static members any way (since it generally doesn't have an object to work on).
But that only applies to implicit access - there's nothing stopping you from accessing object data through an explicit this pointer, providing you follow the access rules (e.g., no access to private data).
The fourth parameter is passed to the thread when it starts. QThreadPrivate::start can use it (after an appropriate cast) to call an object specific member function.
Related
If a pointer to a structure, inside one function, is dereferenced and passed as an argument to another function how does one access the structure's members inside that function?
For instance, a pointer to a structure is passed to a function like this:
main_logic_tick(&settings);
Inside the main_logic_tick function, the pointer is dereferenced and passed as an argument to another function (i.e. tick()):
void main_logic_tick(Settings* settings)
{
//...
state_machine.tick(*settings);
}
How do I access members of the stucture Settings via the settings-variable inside the tick()-function above? Is it a call by value or a call by reference? And finally, how should the function prototype for the tick()-function look like?
How do I access members of the stucture Settings via the settings-variable inside the tick()-function above? Is it a call by value or a call by reference? And finally, how should the function prototype for the tick()-function look like?
tick() can accept the Settings object by value or by reference. It sounds like you want it to accept its argument by reference -- that you want to be able modify the object and have the modifications be visible two functions upstream. For that, you would use:
void tick(Settings& settings);
Inside tick you would use the usual syntax for accessing members of a reference -- using the dot (.) operator.
settings.member = new_value;
While calling pointer to member function, we need to explicitly specify this:
(this->*ptr)();
If I understand correctly, we need to do that, since automatic parameter (this) passing doesn't work in this cases (maybe because we call member function using pointer to it). So I wonder, why can't we just call it and explicitly pass this as parameter?
ptr(this); / compile error
I always wondered why there is a stylistic difference between calling a pointer to function vs calling a pointer to a member function in terms of using the de-referencing operator *, i.e.
void(*fptr)()=&f; // pointer to function f()
fptr(); // call f() via pointer to function
Foo foo; // instance of Foo
void (Foo::*fptr)()=&Foo::f; // pointer to member function f()
(foo.*fptr)(); // call foo.f() via pointer to member function
In the first part, you don't use the * operator to call f() via the function pointer, but then one must use it in calling the member function via the pointer, (foo.*fptr)(). Why this difference? Why not just use (foo.fptr)() for consistency? Is there any profound reason or just this is the way C++ was designed?
I'll be quoting stuff from C++ Common Knowledge. The related chapter is titled Pointers to member functions are not pointers. There the author explains why pointers to member functions cannot be implemented as pointer to functions. I'll be using this (the fact that they're different things) as a justification for the different syntax :
When you take the address of a non-static member function, you don't get an address; you get a pointer to member function.
(...)
As with a pointer to data member, we need an object or pointer to an object in order to dereference a pointer to member function. (...) In the case of a pointer to member function, we need the object's address to use as (or to calculate) the value of the this pointer for the function call and possibly for other reasons as well.
Note that there is no such thing as a "virtual" pointer to member function. Virtualness is a property of the member function itself, not the pointer that refers to it.
This is one reason why a pointer to member function cannot be implemented, in general, as a simple pointer to function. The implementation of the pointer to member function must store within itself information as to whether the member function to which it refers is virtual or nonvirtual, information about where to find the appropriate virtual function table pointer, an offset to be added to or subtracted from the function's this pointer and possibly other information. A pointer to member function is commonly implemented as a small structure that contains this information, although many other implementations are also in use.
Dereferencing and calling a pointer to member function usually involves examining the stored information and conditionally executing the appropriate virtual or nonvirtual function calling sequence.
IMHO considering these differences one can justify the syntax difference, although historic design choices could have played their role.
If we simply use foo.fptr, it is the same as how we call a member function, making the compiler complex. Actually, fptr is not a member function of foo. Thus *fptr shows the difference. Maybe the compile can make that happen ,and I think that's how C++ was designed now.
why does thread procedure should be static or member function?
any valid reason?
Non-static member variables have an implicit this parameter passed by the compiler internally.
You have
ClassInQuestion {
void threadFunc( int );
}
and the compiler internally creates a function
void ClassInQuestion_threadFunc( ClassInQuestion* thisObject, int );
So unless the thread procedure accepts a pointer t a function that has a first parameter of type ClassInQuestion* it will not match the expected function signature.
Mainly because non static member functions have an implicit parameter, making it hard to fill in in a function pointer. I guess that when specifying a non static member function, you would also expect the object to be known, which is different from how functions otherwise work.
Typically, the thread procedures have to be called by the predefined functions in the thread libraries with callback mechanism. To be able to call a member function (not static), you need an object of the class which would invoke the function. However, none of the available thread libraries support this i.e. they do no accept the object which would be used to call the registered function. So all such functions should be made static and type casted appropriately.
In C++, if an object of a class is passed as a parameter into a function, the copy constructor of the class will be called.
I was wondering if the object is of nonclass type, what function will be called?
Similarly in C, what function is called when passing values or address of variables into a function?
Thanks and regards!
No function will be called; the bytes composing the object will simply be copied to the correct place for the callee (be that a location in memory or a register).
The copy constructor is only called if the object is being passed by value (and is a non-POD type). This is one of the reasons that it is common practice to pass objects by reference and const reference should you not wish the object to be changed by the function.
No function is called.
Since non-object types don't have methods, they are simply copied onto the stack to be used as-is by your function.
It depends on the implementation, but in some cases you may incur a function call if you are passing a floating-point value into a function expecting a value of integral type. (This is an implementation detail rather than part of the language, it's true, but it's no less worth taking account of because of that. And such conversions are often slow in any event, function call required or not.)