2012-06-05 8 views
13

Breve introducción: Estoy trabajando en el código multiproceso y tengo que compartir objetos asignados dinámicamente entre dos hilos. Para hacer mi código más limpio (y menos propenso a errores) quiero explícitamente "eliminar" objetos en cada hilo y es por eso que quiero usar shared_ptr.Sobrecarga e implementación del uso de shared_ptr

Primera pregunta:

Quiero saber si la implementación de -> operator en shared_ptr tiene cierta sobrecarga adicional (por ejemplo, más grande que unique_ptr) durante el tiempo de ejecución. Los objetos a los que me refiero son generalmente instancias de larga duración copiadas solo una vez después de la creación (cuando las distribuyo entre subprocesos), entonces solo accedo a los métodos y campos de estos objetos.

Soy consciente de que shared_ptr solo protege el recuento de referencias.

Segunda pregunta:

¿Qué tan bien están optimizados en shared_ptr libstdC++? ¿Siempre usa mutex o aprovecha las operaciones atómicas (me centro en las plataformas x86 y ARM)?

+3

En una buena implementación de 'shared_ptr', debe haber cero sobrecarga al desreferenciar el puntero mediante' -> '. No estoy familiarizado con libstdC++, así que no puedo responder tu segunda pregunta. Sin embargo, tiene los encabezados, por lo que puede averiguar fácilmente al observar cómo se implementa. –

+2

Si el código es multiproceso, el puntero compartido de GCC usa un 'std :: atomic ' o algo así para el contador de referencia; si ese es un hardware verdadero (sin bloqueo) atómico depende de la versión del compilador, creo que esto fue mejorado en GCC 4.7.0. –

+3

Copiar/asignar/salir del alcance tiene una sobrecarga adicional debido al incremento en el número de subprocesos del recuento. 'operator->' se ve exactamente igual a la del antiguo 'auto_ptr', es decir, se puede esperar que sea cero. – Damon

Respuesta

14

Primera pregunta: usando operator->

Todas las implementaciones que he visto tiene una caché local de T* justo en la clase shared_ptr<T> para que el campo esté en la pila, operator-> tiene así una comparables costo para utilizar una pila local T*: sin gastos generales.

Segunda pregunta: mutex/atómicas

espero libstdC++ para usar armas atómicas en la plataforma x86, ya sea a través de las instalaciones estándar o G intrínsecos específicos ++ (en las versiones anteriores). Creo que la implementación de Boost ya lo hizo.

No obstante, no puedo comentar sobre ARM.

Nota: C++ 11 que introduce la semántica del movimiento, muchas copias se evitan naturalmente en el uso de shared_ptr.

Nota: leer uso correcto de shared_ptr sobre here, puede utilizar referencias a shared_ptr (const o no) para evitar la mayoría de las copias/destrucción en general, por lo que el rendimiento de los que no es demasiado importante.

+0

en la respuesta que adjuntó se dice que usa 'make_shared'. Me pregunto cómo usar esta plantilla en la lista de inicialización del constructor. Ejemplo, la clase 'Foo' tiene el campo' shared_ptr num', por lo que el constructor debe tener el siguiente aspecto: 'Foo :: Foo (void): num (move (make_shared (new int (30)))) {...}' ? – Goofy

+2

@Goofy: no, con 'make_shared' no realiza el' nuevo' explícitamente y, por otro lado, necesita pasar el tipo del objeto creado explícitamente; también la llamada a 'mover' es innecesaria en un temporal. Por lo tanto, produce: 'Foo :: Foo(): num (std :: make_shared (30)) {}' –

+0

Ok, genial :) Todavía me estoy acostumbrando a los valores en C++;) – Goofy

12

El shared_ptr de GCC no usará ningún bloqueo o atomics en el código de un solo subproceso. En el código de subprocesos múltiples, utilizará operaciones atómicas si la CPU admite una instrucción atómica de comparación e intercambio, de lo contrario, los recuentos de referencia estarán protegidos por un mutex. En i486 y luego usa atomics, i386 no es compatible con cmpxchg, por lo que usa una implementación basada en mutex. Creo que ARM usa átomos para la arquitectura ARMv7 y más tarde.

(Lo mismo se aplica a ambos std::shared_ptr y std::tr1::shared_ptr.)

+1

¿Cómo sabe GCC si el el código es/será multihilo o no? –

+0

@DrewNoakes - tiene que decirlo con #define. –

+0

¿Tiene una referencia para esto? He hecho una pequeña búsqueda y no puedo encontrar ninguna. –

Cuestiones relacionadas