Pretty self explanatory question. For example, the header for pthread_create shows it takes a pointer to a thread:
int WINPTHREAD_API pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg);
OK, makes sense, you allocate a pthread in memory then pass a pointer to pthread_create so it gets initialized... but now looking at the header for pthread_join:
int WINPTHREAD_API pthread_join(pthread_t t, void **res);
It takes a copy of the pthread_t. I just don't get why it doesn't take a pointer to that already existing thread, rather than copying it and passing it over; it seems like if anything, doing so would cause more problems and more memory use. Am I missing something? I read the manpage, it doesn't seem to offer a reason to this.
CodePudding user response:
It takes a copy of the
pthread_t
.
Yes.
I just don't get why it doesn't take a pointer to that already existing thread,
pthread_t
is a thread identifier. The specs consistently refer to it that way. Copying it does not duplicate the thread itself, nor consume more memory than one pthread_t
occupies.
rather than copying it and passing it over; it seems like if anything, doing so would cause more problems and more memory use.
It does not necessarily cause more memory use, as a pthread_t
is not necessarily larger than a pointer. It might be a pointer, or an integer. Even if it is a structure, however, there is no reason to think that it so large that passing it by value presents a significant problem, because the specifics are under control of the pthreads implementation. Why would implementers shoot themselves in the foot that way? Note well that passing a structure by value is not inherently less efficient than passing a pointer.
As for problems other than excessive memory use, you would have to be more specific, but I don't see any issues inherent in accessing a copy of a thread identifier directly vs. accessing a common identifier object indirectly, for the purposes of those functions that accept a pthread_t
by value.
Am I missing something?
I suspect that your concerns are tied up in a misunderstanding of type pthread_t
as somehow carrying data supporting thread operation as opposed to simply identifying a thread.
You may also be supposing that pthreads is a library, with a particular implementation, whereas in fact, it is first and foremost a specification, designed to afford multiple implementations. This is part of the reason for defining abstract data type pthread_t
instead of specifying int
or struct something *
-- implementations can choose what actual type to use.
Perhaps you are also focusing too closely on the API functions. Even if in some particular implementation, passing a pthread_t
by value to, say, pthread_join()
were less efficient than passing a pointer to one, how much of an impact do you suppose that would actually have? pthread_join()
is called infrequently, and only in cases where the caller is prepared to block. What does it matter if argument passing consumes a few more nanoseconds than it might otherwise do?
I read the manpage, it doesn't seem to offer a reason to this.
Few manual pages provide rationale for function design, but I think the most likely explanation is essentially that form follows function. Those functions that receive a pthread_t
by value do so because they do not need or want to modify the caller's value. The functions' designs reflect that.
CodePudding user response:
A pthread_t
is a small object which identifies a thread. It could be a pointer, integer or perhaps a tiny structure. The pthread_t
isn't actually the thread itself any more than a HWND
object in Win32 is the window itself.
The pthread_create
function returns this identifier via a pointer pointer because it already returns a value of type int
for error indication. Other functions take pthread_t
by value.
For instance, to compare whether two pthread_t
objects refer to the same thread, you should use pthread_equal
, which takes two pthread_t
parameters. It's possible that all this function does is compare the two values using ==
, but doing that directly wouldn't be as portable. It won't even compile if pthread_t
happens to be a small structure.