0

As the title says, I'm curious as to why thread functions accept only one void * argument instead of how a normal function accepts whatever arguments you want to pass in:

#include <pthread.h>

int pthread_create(pthread_t *restrict thread,
                const pthread_attr_t *restrict attr,
                void *(*start_routine)(void *),
                void *restrict arg);

I'm talking about that last arg in pthread_create which gets passed to start_routine.

I know that you can condense multiple arguments into a struct and then pass a pointer to it, but I don't understand why, I couldn't find a single lead that can help me answer the question.

soufiane yakoubi
  • 861
  • 11
  • 31
  • 2
    ...because that's all the OS provides in it's 'CreateThread()' API. The argument has to be copied onto a new stack and the new thread has to recover the parameter. The OS can do that, but only for a fixed size argument, so the OS designers chose a pointer - if you can pass a pointer, you can pass anything:) – Martin James Oct 17 '21 at 12:22
  • 1
    What else would you need? If you want more parameters, how many? What types? What would all those thousands threads do that don't need such parameters? Whatever number you pick, you can't make it perfect for everyone. But you can make it work for everyone. If you can't make it work with one pointer, you need to rethink your approach. – Gerhardh Oct 17 '21 at 12:27
  • @MartinJames thank you that's what i was looking for, can you rewrite your comment into an answer so that I can accept it? – soufiane yakoubi Oct 17 '21 at 12:31
  • @Gerhardh I think you can probably do anything with a single pointer. I was just curious about the design decision. – soufiane yakoubi Oct 17 '21 at 12:35
  • 1) that is rather opinion based and OT for SO. 2) As I wrote: Other parameter lists might be different but what would make them *better*? Whatever you chose you can immediately ask again "OK, but... WHY?" 3) Also the comment regarding OS might be true for certain OS'es but C is not limited to a certain OS. And it might just be one reason among docens. – Gerhardh Oct 17 '21 at 12:38
  • This is a bit of supposition, but the mechanisms for interpreting variadic arguments were not designed to be re-entrant, so a single argument was substantially easier and safer to implement. – sj95126 Oct 17 '21 at 12:43
  • @sj95126: variadic arguments don't create any race conditions. – rici Oct 17 '21 at 13:44
  • @rici: I don't see how the standard guarantees that in any way. It even specifies that `va_start` shall not be used a second time before a corresponding `va_end` for the same argument list. – sj95126 Oct 17 '21 at 13:59
  • @sj95126: it's not the same argument list in another thread. Every call frame is distinct. (Anyway, you can do `va_copy` if you need to process the argument list more than once. But I still fail to see how that's affected by threads.) – rici Oct 17 '21 at 14:03
  • @rici: Call frames are an implementation detail. The standard does not once include the words "frame" or "stack". Anyway, it wasn't my intention to start a semantics debate. I merely theorized that the **potential** for difficulties made a single argument a simpler implementation. – sj95126 Oct 17 '21 at 14:09
  • @sj95126: that's true, it doesn't. But the existence of call frames (whether or not they are kept on a stack) is implicit in the discussion of the lifetime of automatic variables, and (more to the point) in the requirements for use of `va_list`. In brief, each `va_list` which is initialized must be passed to `va_end` before the function which initialized the `va_list` returns. Once `va_end` is called on a `va_list`, it can no longer be used (except to be reinitialised). The consequence is that a `va_list` cannot be persisted or handed to another thread.... – rici Oct 17 '21 at 22:33
  • 1
    ... which makes race conditions impossible. But it also makes it impossible to write a hypothetical variadic `thread_create`; since it has no way to pass its `va_list` to a thread, and it can't store the individual arguments because it has no way to know their types. Of course, that's moot; no-one would want to have to write every thread function as variadic; that's even uglier than passing a custom `struct`. – rici Oct 17 '21 at 22:36

0 Answers0