2012-03-07 5 views
8

C++ 11 ofrece características como thread-safe initialization of static variables, y citando a esa pregunta vamos a decir por ejemplo:¿Alguna garantía de seguridad de subprocesos de C++ 11 se aplica a bibliotecas de subprocesos de terceros compiladas/vinculadas con C++ 11?

Logger& g_logger() { 
    static Logger lg; 
    return lg; 
} 

Así ostensiblemente esto es cierto independientemente de si un módulo compilado con un compilador de C++ 11 (?) incluía los encabezados de subprocesos o generaba subprocesos en su cuerpo. Se le ofrece la garantía incluso si se vinculó con otro módulo que usó hilos C++ 11 y llamó a la función.

Pero, ¿qué ocurre si su "otro módulo" que llama a este código no utiliza hilos C++ 11, sino algo así como Qt's QThread. ¿Está entonces la inicialización atómica de la estática fuera del alcance de la capacidad de C++ 11 para hacer tal garantía? ¿O el simple hecho de que un módulo haya sido compilado con C++ 11 y luego vinculado con otro código de C++ 11 implica que usted obtendrá la garantía independientemente?

¿Alguien sabe una buena referencia donde se cubren problemas como este?

+0

inicialización estática es una propiedad de idioma. No veo cómo esto puede verse afectado por una biblioteca específica. – pmr

+2

@pmr Me parece un poco complicado porque, por ejemplo, la memoria de la estática anterior se asigna al comienzo del programa, pero el constructor ejecuta la primera vez que se llama a la función con el estático dentro de ella. Parecería requerir una omnisciencia sobre el modelo de subproceso subyacente para lograr esto, por lo que soy escéptico de que podría hacerlo bien si se mezcla QThread/C++ 11thread ... aunque hay una pequeña posibilidad de nuevos requisitos binarios que lo hagan funcionar . – HostileFork

+0

@HostileFork: Siempre que ambos (C++ y qt) utilicen las mismas funciones de sistema operativo para enhebrar, no veo cómo algo podría salir mal. Además, no veo por qué ninguno de los dos debería usar las funciones de subprocesamiento del sistema operativo. – PlasmaHH

Respuesta

4

Su ejemplo se basa en el modelo de memoria, no en cómo se implementan los hilos. Quien ejecuta este código ejecutará las mismas instrucciones. Si dos o más núcleos ejecutan este código, obedecerán al modelo de memoria.

La implementación básica es equivalente a esto:

std::mutex mtx; 
Logger * lg = 0; 
Logger& g_logger() { 
    std::unique_lock<std::mutex> lck(mtx); 
    if (lg == 0) 
     lg = new Logger; 
    return *lg; 
} 

Este código puede ser optimizado para utilizar el patrón de una doble comprobación de bloqueo (DCLP) que, en una arquitectura de procesador particular (por ejemplo, en la x 86) podría ser mucho más rápido. Además, como el compilador genera este código, sabrá que no debe hacer optimizaciones locas que rompan el ingenuo DCLP.

+0

Genial, gracias ... parece que hay consenso de que esto * es * seguro *. FYI: El motivo por el que lo busqué fue abordar este escenario ... http://stackoverflow.com/questions/9507973/how-to-mitigate-user-facing-api-effect-of-shared-members-in -templated-classes – HostileFork

7

¿Alguien sabe una buena referencia donde se cubren problemas como este?

Sure. El estándar de C++. Describe el comportamiento del código C++. Si su biblioteca es código C++, se requiere seguir este comportamiento. Así que sí, obtienes las mismas garantías que si hubiera sido tu propio código.

Exactamente cómo el compilador/tiempo de ejecución/OS/todo lo demás lo quita es No es su problema. El estándar C++ garantiza que se cuide.

+0

Punto tomado. Sin embargo, independientemente de si es mi problema o no, me gustaría saber si uso GCC y Qt si hicieron la magia para "sacarlo". Desde el punto de vista tecnológico, si un C++ 03 'estático.una biblioteca 'se vinculó a un ejecutable C++ 11' icallthestatic 'es poco probable que el enlazador sea capaz de hacer esto. Pero eso apunta a un problema más amplio de "probablemente no se puede vincular el código C++ 03 con C++ 11 y obtener garantías C++ 11 para el sistema" ... – HostileFork

+0

El código C++ 03 solo se garantiza que se comporte como C++ 03. Por lo tanto, si enlaza con una biblioteca C++ 03, no puede contar con la implementación de garantías proporcionadas solo por C++ 11 – jalf