É inteligente replace boost :: thread e boost :: mutex com c ++ 11 equivalentes?

Motivação: pelo que estou considerando é que meu genial gerente de projeto acha que boost é outra dependência e que é horrível porque “você depende disso” (tentei explicar a qualidade do boost, depois desisti depois de algum tempo 🙁 Menor razão pela qual eu gostaria de fazer é que eu gostaria de aprender os resources do c ++ 11, porque as pessoas vão começar a escrever código nele.

  1. Existe um mapeamento 1: 1 entre #include #include e aumenta os equivalentes?
  2. Você consideraria uma boa idéia replace o boost boost pelo c ++ 11
    coisa. Meu uso é primitivo, mas há exemplos quando o std não oferece o que o boost faz? Ou (blasfêmia) vice-versa?

PS Eu uso o GCC, então os headers estão lá.

Existem várias diferenças entre o Boost.Thread e a biblioteca de threads padrão do C ++ 11:

  • Boost suporta cancelamento de thread, threads C ++ 11 não
  • O C ++ 11 suporta std::async , mas o Boost não
  • Boost tem um boost::shared_mutex para o boost::shared_mutex de múltiplos leitores / single-writer. O std::shared_timed_mutex análogo está disponível somente desde C ++ 14 ( N3891 ), enquanto std::shared_mutex está disponível somente desde C ++ 17 ( N4508 ).
  • Os tempos limite do C ++ 11 são diferentes dos tempos limite do Boost (embora isso mude em breve agora, o Boost.Chrono foi aceito).
  • Alguns dos nomes são diferentes (por exemplo, boost::unique_future vs std::future )
  • A semântica de passagem de argumentos de std::thread é diferente de boost::thread — Boost usa boost::bind , que requer argumentos copiáveis. std::thread permite que os tipos somente de movimento, como std::unique_ptr sejam passados ​​como argumentos. Devido ao uso de boost::bind , a semântica de espaços reservados como _1 em expressões de vinculação aninhadas também pode ser diferente.
  • Se você não chamar explicitamente join() ou detach() , o operador boost::thread eo operador de atribuição chamarão detach() no object thread que está sendo destruído / designado. Com um object C ++ 11 std::thread , isso resultará em uma chamada para std::terminate() e abortará o aplicativo.

Para esclarecer o ponto sobre os parâmetros somente de movimento, o seguinte é válido em C ++ 11 e transfere a propriedade do int do temporário std::unique_ptr para o parâmetro de f1 quando o novo thread é iniciado. No entanto, se você usar boost::thread , ele não funcionará, pois usa boost::bind internamente e std::unique_ptr não pode ser copiado. Há também um bug na biblioteca de encadeamentos C ++ 11 fornecida com o GCC que impede que isso funcione, já que ele também usa o std::bind na implementação.

 void f1(std::unique_ptr); std::thread t1(f1,std::unique_ptr(new int(42))); 

Se você estiver usando o Boost, provavelmente poderá alternar para encadeamentos C ++ 11 de forma relativamente indolor se o seu compilador suportar (por exemplo, versões recentes do GCC no linux têm uma implementação quase completa da biblioteca de encadeamentos C ++ 11 disponível em -std=c++0x modo -std=c++0x ).

Se o seu compilador não suportar encadeamentos C ++ 11, você poderá obter uma implementação de terceiros, como Just :: Thread , mas isso ainda é uma dependência.

std::thread é amplamente modelado após boost::thread , com algumas diferenças :

  • As semânticas não copiáveis ​​do one-handle-to-one-os-thread do boost são mantidas. Mas esse segmento é móvel para permitir o retorno do thread das funções de fábrica e a colocação em contêineres.
  • Esta proposta adiciona o cancelamento ao boost::thread , que é uma complicação significativa. Essa alteração tem um grande impacto não apenas no thread, mas também no restante da biblioteca de threads do C ++. Acredita-se que essa grande mudança seja justificável devido ao benefício.
    • O destruidor de segmentos agora deve cancelar a chamada antes de desappend para evitar o vazamento acidental de encadeamentos filhos quando os encadeamentos pais são cancelados.
    • Um membro de desconexão explícito agora é necessário para habilitar a desanexação sem cancelar.
  • Os conceitos de identificador de segmento e identidade de segmento foram separados em duas classs (eles são a mesma class em boost::thread ). Isso é para facilitar a manipulação e o armazenamento da identidade do encadeamento.
  • A capacidade de criar um ID de thread que é garantido para comparar igual a nenhum outro segmento juntável foi adicionado ( boost::thread não tem isso). Isso é útil para o código que quer saber se está sendo executado pelo mesmo thread de uma chamada anterior (mutexes recursivas são um exemplo concreto).
  • Existe uma “porta dos fundos” para obter o identificador de thread nativo para que os clientes possam manipular os threads usando o SO subjacente, se desejado.

Isso é de 2007, então alguns pontos não são mais válidos: boost::thread tem uma function native_handle agora e, como os comentaristas apontam, o std::thread não tem mais o cancelamento.

Não consegui encontrar diferenças significativas entre boost::mutex e std::mutex .

Existe uma razão para não migrar para o std::thread .

Se você estiver usando a vinculação estática, o std::thread ficará inutilizável devido a esses bugs / features do gcc:

Ou seja, se você chamar std::thread::detach ou std::thread::join isso resultará em exceção ou travamento, enquanto boost::thread funcionará bem nesses casos.

Caso Empresarial

Se você está escrevendo software para a empresa que precisa rodar em uma variedade moderada a grande de sistemas operacionais e, consequentemente, construir com uma variedade de compiladores e versões de compiladores (especialmente os antigos) nesses sistemas operacionais, minha sugestão é ficar longe de C ++ 11 por enquanto. Isso significa que você não pode usar o std::thread , e eu recomendo usar o boost::thread .

Caso de boot básico / tecnológico

Se você está escrevendo para um ou dois sistemas operacionais, você sabe com certeza que você só precisará compilar com um compilador moderno que suporta principalmente C ++ 11 (por exemplo, VS2015, GCC 5.3, Xcode 7), e você ainda não está dependente da biblioteca de reforço, então std::thread poderia ser uma boa opção.

Minha experiência

Pessoalmente, sou parcial em relação a bibliotecas altamente rígidas, altamente usadas e altamente compatíveis, como o boost versus uma alternativa bastante moderna. Isso é especialmente verdadeiro para assuntos complicados de programação, como encadeamento. Além disso, tenho experimentado um grande sucesso com o boost::thread (e o boost em geral) através de uma vasta gama de ambientes, compiladores, modelos de threads, etc. Quando é minha escolha, eu escolho boost.

Com o Visual Studio 2013, o std::mutex parece se comportar de maneira diferente do boost::mutex , o que me causou alguns problemas (veja essa questão ).

Eu tentei usar shared_ptr de std em vez de boost e eu realmente encontrei um bug na implementação do gcc desta class. Meu aplicativo estava falhando por causa do destrutor chamado duas vezes (essa class deve ser thread-safe e não deve gerar tais problemas). Depois de mudar para boost :: shared_ptr todos os problemas desapareceram. As implementações atuais do C ++ 11 ainda não estão maduras.

O Boost também possui mais resources. Por exemplo, o header na versão std não fornece serializador para um stream (ou seja, cout << duration). O Boost possui muitas bibliotecas que usam seus próprios equivalentes, etc., mas não cooperam com as versões padrão.

Para resumir – se você já tem um aplicativo escrito usando boost, é mais seguro manter seu código como está, em vez de se esforçar para mudar para o padrão C ++ 11.