2010-04-22 9 views
6

Supongamos que tengo mis propias funciones no en línea LockMutex y UnlockMutex, que están usando mutex adecuado, como boost, en el interior. ¿Cómo sabrá el compilador que no debe reordenar otras operaciones con respecto a las llamadas a LockMutex y UnlockMutex? No puede saber cómo implementaré estas funciones en alguna otra unidad de compilación.Reordenación del compilador alrededor de los límites de mutex?

void SomeClass::store(int i) 
{ 
    LockMutex(_m); 
    _field = i; // could the compiler move this around? 
    UnlockMutex(_m); 
} 

ps: Se supone que uno debe usar instancias de clases para mantener bloqueos para garantizar el desbloqueo. Lo dejé para simplificar el ejemplo.

Respuesta

2

No puede saber cómo voy a poner en práctica estas funciones en alguna otra unidad de compilación.

Ésta es la clave - ya que el compilador no puede saber (en general) sobre la aplicación de las llamadas de función, no puede mover el almacén de _field fuera de esas llamadas a funciones.

general, ya que _field es accesible desde fuera de SomeClass::store() (que no es un local), el compilador no puede saber si o no se modifica por la función externa, por lo que debe realizar la tienda para _field entre los puntos de secuencia llamada a la función .

La plataforma de hardware subyacente podría necesitar alguna atención en forma de barreras de memoria o flujos de caché para hacer frente a las operaciones de almacenamiento en caché o fuera de servicio que ocurren en el hardware. La implementación de la plataforma de las API mutex abordará estos problemas si es necesario.

0

Si el compilador estaba haciendo eso, sería un mal compilador. ;-)

2

En general, un compilador no moverá el código a menos que sepa con certeza que al hacerlo no afectará el comportamiento en tiempo de ejecución.

+0

Correcto. Un compilador de movimiento de código tendrá un modelo de análisis estático de cómo funciona su programa y sus dependencias operacionales/de datos, y preservará esas dependencias. –

+2

Estrictamente hablando, no hay ninguna dependencia entre la variable _field, por ejemplo, y la llamada a LockMutex o UnlockMutex, por lo que preservar las dependencias no ayuda aquí. –

0

Si el compilador no puede garantizar que las llamadas de función no tendrán efectos secundarios que modificarán las variables entre las llamadas, no podrá mover el código. Si la variable es una variable local y nunca ha tomado una referencia o creado un puntero a ella, el compilador podría asumir que es seguro moverse; No lo sé.

+1

Si la variable es local, no es volátil y no se ha tomado un puntero o una referencia, ningún otro subproceso puede acceder a ella. Por lo tanto, en lo que se refiere a tomar un mutex, no importaría si la tienda ocurre antes, después o entre las llamadas de función o si nunca ocurre. –

+0

@Michael Burr, ¿no es eso lo que dije?Si el compilador es lo suficientemente sofisticado, podría determinar que una carga/almacén variable local es seguro para reordenar; si lo hace o no, probablemente depende de la configuración del optimizador. Estaba mirando más allá de los límites de la pregunta donde es obvio que la variable es * no * local. Tal como me preguntaron, cae dentro de mi primera oración: el compilador no tiene forma de conocer los efectos secundarios de LockMutex o UnlockMutex, por lo que no puede reordenar. –

+0

No estaba en desacuerdo; Pensé que estaba aclarando algo que parecía ser incierto al final de la respuesta. No quise que sonara argumentativo si así era como se entendía. –

1

Como está escrito, si las funciones no están en línea, el compilador no moverá la asignación de variable, ya que la llamada puede no estar relacionada con la variable _field, pero debe mantener el orden estricto de las llamadas. Sin embargo, si el compilador decide alinear las llamadas, creo que las tratará como bloques de código independiente, es decir, solo reordenará las instrucciones dentro de la misma unidad de código (la función en sí misma) pero no con la siguiente o anterior código (la asignación a la variable _field).

+0

Gracias. ¿Tiene un enlace a la documentación que indica que el reordenamiento del compilador se detiene en los límites de incluso las funciones en línea? – shojtsy

1

Tienes razón, el código es correcto y seguro. Aunque pensé en una "broma del código".

pthread_mutex_lock(&mx) + foo() + pthread_mutex_unlock(&mx); 
Cuestiones relacionadas