Pregunta bastante autoexplicativa. Por ejemplo, el encabezado de pthread_create muestra que lleva un puntero a un hilo:
int WINPTHREAD_API pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg);OK, tiene sentido, asignas un pthread en la memoria y luego pasas un puntero a pthread_create para que se inicialice... pero ahora mira el encabezado de pthread_join:
int WINPTHREAD_API pthread_join(pthread_t t, void **res);Toma una copia de pthread_t. Simplemente no entiendo por qué no lleva un puntero a ese hilo ya existente, en lugar de copiarlo y pasarlo; parece que, en todo caso, hacerlo causaría más problemas y más uso de memoria. ¿Me estoy perdiendo de algo? Leí la página de manual, no parece ofrecer una razón para esto.
Toma una copia de
pthread_t.
Sí.
Simplemente no entiendo por qué no lleva un puntero a ese hilo ya existente,
pthread_t es un identificador de hilo. Las especificaciones constantemente se refieren a él de esa manera. Copiarlo no duplica el hilo en sí, ni consume más memoria de la que ocupa un pthread_t .
en lugar de copiarlo y pasarlo; parece que, en todo caso, hacerlo causaría más problemas y más uso de memoria.
No necesariamente causa más uso de memoria, ya que pthread_t no es necesariamente más grande que un puntero. Puede ser un puntero o un número entero. Sin embargo, incluso si se trata de una estructura, no hay razón para pensar que es tan grande que pasarla por valor presenta un problema significativo, porque los detalles están bajo el control de la implementación de pthreads. ¿Por qué los implementadores se pegarían un tiro en el pie de esa manera? Tenga en cuenta que pasar una estructura por valor no es inherentemente menos eficiente que pasar un puntero.
En cuanto a los problemas que no sean el uso excesivo de memoria, tendría que ser más específico, pero no veo ningún problema inherente al acceso directo a una copia de un identificador de subproceso frente a . acceder indirectamente a un objeto identificador común, a los efectos de aquellas funciones que aceptan un pthread_t por valor.
¿Me estoy perdiendo de algo?
Sospecho que sus preocupaciones están ligadas a un malentendido del tipo pthread_t como que de alguna manera transporta datos que respaldan la operación del subproceso en lugar de simplemente identificar un subproceso.
También puede estar suponiendo que pthreads es una biblioteca, con una implementación particular, mientras que, de hecho, es ante todo una especificación , diseñada para permitir múltiples implementaciones. Esta es parte de la razón para definir el tipo de datos abstracto pthread_t en lugar de especificar int o struct something * -- las implementaciones pueden elegir qué tipo real usar.
Quizás también se esté enfocando demasiado en las funciones de la API. Incluso si en alguna implementación en particular, pasar un pthread_t por valor a, digamos, pthread_join() fuera menos eficiente que pasar un puntero a uno, ¿cuánto impacto supone que tendría realmente? pthread_join() se llama con poca frecuencia, y solo en los casos en que la persona que llama está preparada para bloquear. ¿Qué importa si la aprobación de argumentos consume unos nanosegundos más de lo que consumiría de otro modo?
Leí la página de manual, no parece ofrecer una razón para esto.
Pocas páginas de manual brindan una justificación para el diseño de funciones, pero creo que la explicación más probable es esencialmente que la forma sigue a la función. Aquellas funciones que reciben un pthread_t por valor lo hacen porque no necesitan ni quieren modificar el valor de la persona que llama. Los diseños de las funciones reflejan eso.
Un pthread_t es un pequeño objeto que identifica un hilo. Podría ser un puntero, un número entero o quizás una pequeña estructura. El pthread_t no es en realidad el hilo en sí más que un objeto HWND en Win32 es la ventana en sí.
La función pthread_create devuelve este identificador a través de un puntero porque ya devuelve un valor de tipo int para la indicación de error. Otras funciones toman pthread_t por valor.
Por ejemplo, para comparar si dos objetos pthread_t se refieren al mismo hilo, debe usar pthread_equal , que toma dos parámetros pthread_t . Es posible que todo lo que haga esta función sea comparar los dos valores usando == , pero hacerlo directamente no sería tan portátil. Ni siquiera se compilará si pthread_t resulta ser una estructura pequeña.
Una cosa a tener en cuenta es que pthread es una API de C. A diferencia de C++, que tiene constructores, se garantiza que copiar una variable de C es razonablemente económico. El peor de los casos sería un tipo que es una estructura grande, pero incluso entonces, es solo un memcpy. Esto es diferente a C++ donde una copia puede invocar un constructor arbitrariamente costoso.