programming how from example curso compiler code caracteristicas c++ c

c++ - how - extern c



Inicializando mutexes pthread (5)

"Funciona" si todas las instancias de myMutex deben compartir el mismo mutex POSIX. Actualmente tiene un mutex y no uno por objeto MyClass. Esto ciertamente no es lo que quieres, ¿no?

De acuerdo con la documentation un mutex puede inicializarse de dos maneras:

Usando la función init:

pthread_mutex_t theMutex; pthread_mutex_init(&theMutex, NULL);

Usando una macro inicializadora:

pthread_mutex_t result = PTHREAD_MUTEX_INITIALIZER;

Sobre este último la documentación dice:

En los casos en que los atributos de exclusión mutua predeterminados sean apropiados, la macro PTHREAD_MUTEX_INITIALIZER se puede usar para inicializar las exclusiones mutuas que se asignan de forma estática. El efecto será equivalente a la inicialización dinámica mediante una llamada a pthread_mutex_init () con el parámetro attr especificado como NULL, excepto que no se realizan comprobaciones de errores.

¿Esto significa que solo se puede usar para variables estáticas y no para variables locales?

Específico de C ++

Quería usar la siguiente "función de fábrica":

static pthread_mutex_t GetFastNativeMutex() { static pthread_mutex_t result = PTHREAD_MUTEX_INITIALIZER; return result; }

Porque me permitiría inicializar mutexes en una lista de inicializadores de C ++ de la siguiente manera:

MyClass() : myMutex(GetFastNativeMutex()) {}

¿Esto es válido? (Por cierto, en la práctica funciona. Valgrind tampoco se queja).

Actualizar

Si entendí la documentación correctamente, entonces esto debería estar bien:

#include <pthread.h> static pthread_mutex_t m0 = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;

Sin embargo, cuando veo la salida del preprocesador (usando gcc -E main.cpp ) veo lo siguiente:

static pthread_mutex_t m0 = {0x32AAABA7, {0}}; static pthread_mutex_t m1 = {0x32AAABA7, {0}}; static pthread_mutex_t m2 = {0x32AAABA7, {0}};

Resulta que tres veces se creó el mismo mutex. ¿Qué estoy haciendo mal aquí?


Estándar no permite copiar las exclusiones mutuas por valor o devolverlas por valor. Vea documentation , el párrafo que habla explícitamente de esto, diciendo "IEEE Std 1003.1-2001 no define asignación o igualdad para este tipo [pthread_mutex_t]"

El pariente más cercano de pthread_mutex, WIN32 CriticalSection, es absolutamente imposible de copiar y no se puede devolver por valor. Así que tu API será muy no portátil de todos modos.

Recomiendo que no se copie (devuelva) la exclusión mutua por valor, incluso si puede probarlo y funciona.

Tenga en cuenta que inicializar un mutex es diferente de copiar el mutex ya inicializado.


Re "Resulta que tres veces se creó el mismo mutex. ¿Qué estoy haciendo mal aquí?"

No estás haciendo nada malo aquí. El mismo mutex no fue creado tres veces. Parece que estás interpretando ese 0x32AAABA7 como una dirección. No lo es Es esencialmente un valor de enumeración, pero con un código de protección de Hamming para (a) hacerlo seguro y (b) hacerlo oscuro. Usted tiene tres mutexes diferentes aquí.


Solo porque puedes hacerlo, no significa que debas hacerlo.

La documentación especifica claramente que usas pthread_mutex_init en tiempo de ejecución y la otra macro para las exclusiones mutuas asignadas estáticamente, no veo ninguna razón para no hacerlo.


Su GetFastNativeMutex es de ninguna manera una función de fábrica. Siempre devuelve la copia del mismo mutex, el punto de fábrica es abstraer la asignación y la creación de un nuevo objeto, no reutilizar el mismo todo el tiempo. Entonces, no, esto no es válido para cualquier uso que no se haría usando el mismo mutex como una variable global.

Una cita de documentation :

El resultado de referirse a copias de mutex en llamadas a pthread_mutex_lock (), pthread_mutex_trylock (), pthread_mutex_unlock (), y pthread_mutex_destroy () no está definido.