lock_guard - ¿Es inteligente reemplazar boost:: thread y boost:: mutex con c++ 11 equivalentes?
mutex example (6)
Motivación: por lo que estoy considerando es que mi genio gerente de proyecto piensa que impulsar es otra dependencia y que es horrible porque "usted depende de eso" (traté de explicar la calidad del impulso, luego me rendí después de un tiempo :( ). Una razón más pequeña por la que me gustaría hacerlo es que me gustaría aprender las características de c ++ 11, porque las personas comenzarán a escribir código en él.
- ¿Hay un mapeo 1: 1 entre
#include<thread> #include<mutex>
y aumente los equivalentes? - ¿Consideraría una buena idea reemplazar las mejoras con c ++ 11?
cosas. Mi uso es primitivo, pero ¿hay ejemplos cuando std no ofrece lo que hace boost? O (blasfemia) viceversa?
PD: uso GCC para que los encabezados estén allí.
Con Visual Studio 2013, std::mutex
parece comportarse de manera diferente que boost::mutex
, lo que me causó algunos problemas (vea esta pregunta ).
Hay una razón para no migrar a std::thread
.
Si está utilizando enlaces estáticos, std::thread
vuelve inutilizable debido a estos errores / funciones de gcc:
A saber, si llama a std::thread::detach
o std::thread::join
dará lugar a excepción o crash, mientras boost::thread
funciona bien en estos casos.
Hay varias diferencias entre Boost.Thread y la biblioteca de hilos estándar de C ++ 11:
- Boost admite la cancelación de subprocesos, C + + 11 subprocesos no
- C ++ 11 admite
std::async
, pero Boost no - Boost tiene un
boost::shared_mutex
para elboost::shared_mutex
de múltiples lectores / escritor único. Elstd::shared_timed_mutex
análogo está disponible solo desde C ++ 14 ( N3891 ), mientras questd::shared_mutex
está disponible solo desde C ++ 17 ( N4508 ). - Los tiempos de espera de C ++ 11 son diferentes a los tiempos de espera de Boost (aunque esto debería cambiar pronto, ahora se ha aceptado Boost.Chrono).
- Algunos de los nombres son diferentes (por ejemplo,
boost::unique_future
vsstd::future
) - La semántica de argumento de paso de
std::thread
es diferente paraboost::thread
--- Boost usaboost::bind
, que requiere argumentos para copiar.std::thread
permite pasar tipos de solo movimiento comostd::unique_ptr
como argumentos. Debido al uso deboost::bind
, la semántica de marcadores de posición como_1
en expresiones de enlace anidado también puede ser diferente. - Si no llama explícitamente a
join()
odetach()
,boost::thread
destructor y el operador de asignación llamarán adetach()
en el objeto thread que está siendo destruido / asignado. Con un objeto C ++ 11std::thread
, esto dará como resultado una llamada astd::terminate()
y abortará la aplicación.
Para aclarar el punto sobre los parámetros solo de movimiento, lo siguiente es C ++ 11 válido, y transfiere la propiedad del int
del std::unique_ptr
temporal al parámetro de f1
cuando se inicia el nuevo hilo. Sin embargo, si usa boost::thread
, no funcionará, ya que usa boost::bind
internamente, y std::unique_ptr
no se puede copiar. También hay un error en la biblioteca de hilos de C ++ 11 provisto con GCC que evita que esto funcione, ya que usa std::bind
en la implementación allí también.
void f1(std::unique_ptr<int>);
std::thread t1(f1,std::unique_ptr<int>(new int(42)));
Si está utilizando Boost entonces probablemente pueda cambiar a C ++ 11 hilos relativamente sin problemas si su compilador lo admite (por ejemplo, las versiones recientes de GCC en Linux tienen una implementación mayoritariamente completa de la biblioteca de hilos de C ++ 11 disponible en -std=c++0x
).
Si su compilador no admite subprocesos de C ++ 11, entonces es posible que pueda obtener una implementación de terceros como Just :: Thread , pero esto sigue siendo una dependencia.
Intenté usar shared_ptr desde std en lugar de boost y encontré un error en la implementación de gcc de esta clase. Mi aplicación se estaba bloqueando debido a que destructor llamó dos veces (esta clase debería ser segura para subprocesos y no debería generar tales problemas). Después de mover a boost :: shared_ptr, todos los problemas desaparecieron. Las implementaciones actuales de C ++ 11 aún no están maduras.
Boost también tiene más funciones. Por ejemplo, el encabezado en la versión estándar no proporciona el serializador a una transmisión (es decir, cout << duration). Boost tiene muchas bibliotecas que usan sus propios equivalentes, etc., pero no cooperan con las versiones estándar.
En resumen, si ya tiene una aplicación escrita usando boost, es más seguro mantener su código como está, en lugar de esforzarse para pasar al estándar C ++ 11.
std::thread
está modelado en gran medida después de boost::thread
, con algunas diferencias :
- Las semánticas de boost que no se pueden copiar y que se manejan con un solo identificador son ocultas. Pero este hilo se puede mover para permitir el retorno del hilo desde las funciones de fábrica y su colocación en contenedores.
- Esta propuesta agrega cancelación al
boost::thread
, que es una complicación significativa. Este cambio tiene un gran impacto no solo en el hilo, sino también en el resto de la biblioteca de threads C ++. Se cree que este gran cambio es justificable debido al beneficio.
- El destructor de subprocesos ahora debe llamar cancelar antes de separarse para evitar filtrar accidentalmente subprocesos secundarios cuando se cancelan subprocesos principales.
- Ahora se requiere un miembro de separación explícito para permitir la separación sin cancelar.
- Los conceptos de identificador de subprocesos e identidad de subprocesos se han separado en dos clases (son de la misma clase en
boost::thread
). Esto es para facilitar la manipulación y el almacenamiento de la identidad del hilo.- Se ha agregado la capacidad de crear un id. De subproceso que se garantiza que se compara igual a ningún otro subproceso que se pueda unir (
boost::thread
no tiene esto). Esto es útil para el código que quiere saber si se está ejecutando con el mismo hilo que una llamada anterior (los mutex recursivos son un ejemplo concreto).- Existe una "puerta trasera" para obtener el manejador de subproceso nativo para que los clientes puedan manipular subprocesos utilizando el sistema operativo subyacente, si así lo desean.
Esto es de 2007, por lo que algunos puntos ya no son válidos: boost::thread
tiene ahora una función native_handle
y, como comentan los comentaristas, std::thread
ya no tiene cancelación.
No pude encontrar ninguna diferencia significativa entre boost::mutex
y std::mutex
.
Caso de la empresa
Si está escribiendo software para la empresa que necesita ejecutarse en una variedad moderada a grande de sistemas operativos y, en consecuencia, compila con una variedad de compiladores y versiones compiladoras (especialmente las relativamente antiguas) de esos sistemas operativos, mi sugerencia es mantenerse alejado de C ++ 11 en conjunto por ahora. Eso significa que no puede usar std::thread
, y le recomendaría usar boost::thread
.
Funda de inicio básica / técnica
Si está escribiendo para uno o dos sistemas operativos, está seguro de que solo tendrá que compilar con un compilador moderno que en su mayoría sea compatible con C ++ 11 (por ejemplo, VS2015, GCC 5.3, Xcode 7), y usted no está ya Depende de la biblioteca de impulso, entonces std::thread
podría ser una buena opción.
Mi experiencia
Personalmente, soy partidario de bibliotecas reforzadas, altamente utilizadas, altamente compatibles y altamente consistentes, como el impulso frente a una alternativa muy moderna. Esto es especialmente cierto para temas complicados de programación como el enhebrado. Además, he experimentado un gran éxito con boost::thread
(y boost en general) en una amplia gama de entornos, compiladores, modelos de subprocesamiento, etc. Cuando es mi elección, elijo boost.