alocador personalizado usando movimento para vetor de thread
-
25-09-2019 - |
Pergunta
Atualmente estou aprendendo sobre simultaneidade em C++ e me deparei com o uso de um vetor de threads, o que acredito que será possível em C++0x.No entanto, meu compilador atual não parece ter uma implementação de contêineres com reconhecimento de movimentação e, portanto, recebo erros gerados porque std::thread::thread(const std::thread&)
é excluído, ou seja, só posso usar o construtor de movimento/atribuição de movimento com std::thread
.
Estou correto ao pensar que poderia contornar esse problema escrevendo um alocador personalizado usando
void MyAllocator::construct (pointer p, reference val)
/* should be non-const reference to val because using move constructor? */
{
new ((void*)p) T (std::move(val));
}
em vez de
void allocator::construct (pointer p, const_reference val)
{
new ((void*)p) T (val);
}
?Ou alguma outra variação deste tema (possivelmente usando uma sobrecarga de MyAllocator::construct).
Observação:O objetivo principal é ser um exercício educacional de curto prazo e um trabalho de desempenho suficientemente bom para brincar com threads em contêineres.eu só usaria MyAllocator
nesse contexto.No entanto, por favor, indique-me também quaisquer bibliotecas que possam ter isso implementado para que eu possa dar uma olhada no código-fonte.
Solução
Se o seu compilador não fornecer uma consciência de movimento std::vector
Então você terá que escrever sua própria especialização de std::vector<std::thread>
em vez de apenas fornecer um alocador personalizado. Todo o C ++ 03 vector
A interface depende da cópia: push_back()
copia elementos em; resize()
inicializa os elementos vazios com um cópia de do elemento aprovado como o segundo parâmetro (mesmo que esse seja o valor padrão de T()
); resize()
, reserve()
, insert()
, erase()
e push_back()
vai cópia de elementos se o vetor precisar de realocação, ou elementos precisarão se mover e assim por diante.
Este é um problema tão comum que incluí essa especialização com o meu (comercial) apenas :: thread implementação de std::thread
.
Outras dicas
A maneira mais fácil de contornar o problema seria alocar os fios na pilha e manipular ponteiros para eles.
Verifica a Boost Pointer Container
biblioteca: boost::ptr_vector<std::thread>
Parece -me o que você está procurando.
O requisito de que os contêineres std aceitem apenas objetos copiáveis tem mais a ver com as interfaces do contêiner C++ 03 do que com a implementação do alocador.Por exemplo
vector<T> b(100);
vector<T> a;
a=b;
assert(a==b);
O padrão nos garante que a==b é verdadeiro.No entanto, se T não fosse copiável, então, na melhor das hipóteses, a=b não será compilado; na pior, a=b será indefinido.Além disso,
a.push_back(T());
pode fazer com que um novo espaço seja alocado e, nos bastidores, cópias do antigo sejam feitas para o novo armazenamento subjacente.
Além disso, não há nada no padrão C++03 que diga que uma implementação realmente precisa chamar allocator.construct e, de fato, muitos (gcc, por exemplo) não o fazem.
O padrão C++0x adiciona novas funções de membro à interface do contêiner para tipos móveis e esclarece como coisas como operator= se comportam em sua presença.
Consulte www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2486.pdf