Pergunta

Como você implementar um eficiente e linha sistema seguro contagem de referência no X86 CPUs no C ++ linguagem de programação?

Eu sempre correr para o problema que os operações críticas não atômica , e as operações X86 Interlock disponíveis não são suficientes para implementar o sistema de ref contagem.

O seguinte artigo aborda este tema, mas requer instruções especiais de CPU:

http://www.ddj.com/architect/184401888

Foi útil?

Solução

Hoje em dia, você pode usar o impulso / TR1 shared_ptr <> ponteiro inteligente para manter a sua referência contada referências.

Funciona muito bem; sem barulho, sem bagunça. O shared_ptr <> class cuida de todo o bloqueio necessário no refcount.

Outras dicas

No VC ++, você pode usar _InterlockedCompareExchange .

do
   read the count
   perform mathematical operation
   interlockedcompareexchange( destination, updated count, old count)
until the interlockedcompareexchange returns the success code.

Em outras plataformas / compiladores, utilize o intrínseco apropriado para a instrução BLOQUEIO cmpxchg que expõe _InterlockedCompareExchange de MS.

Estritamente falando, você precisa esperar até C ++ 0x para ser capaz de código thread-safe escrita em puro C ++.

Por enquanto, você pode usar POSIX, ou criar a sua própria plataforma de invólucros independentes em torno de comparar e trocar e / ou intertravado aumentar / diminuir.

Win32 InterlockedIncrementAcquire e InterlockedDecrementRelease (se você quiser ser seguro e se preocupam com plataformas com possível reordenamento, portanto, você precisa barreiras de memória questão ao mesmo tempo) ou InterlockedIncrement e InterlockedDecrement (se tiver certeza de que você vai ficar x86), são atômica e vai fazer o trabalho.

Dito isso, aumentar / TR1 shared_ptr <> vai lidar com tudo isso para você, portanto, a menos que você precisa para implementá-lo em seu próprio país, você provavelmente vai fazer o melhor para cumpri-lo.

Tenha em mente que o bloqueio é muito caro, e isso acontece cada vez que você mão objetos ao redor entre ponteiros inteligentes -. Mesmo quando o objeto é actualmente propriedade de um segmento (a biblioteca ponteiro inteligente não sabe que)

Diante disso, pode haver uma regra aplicável aqui (eu estou feliz em ser corrigido!)

Se as coisas seguem se aplicam a você:

  • Você tem estruturas de dados complexos que seriam difíceis de escrever destruidores para (ou onde semântica de valor de estilo STL seria inapropriado, por design), então você precisa ponteiros inteligentes para fazer isso por você, e
  • Você está usando vários segmentos que compartilham esses objetos, e
  • Você se preocupa com o desempenho, bem como correção

... coleta de lixo, em seguida, real pode ser uma escolha melhor. Embora GC tem uma má reputação para o desempenho, é tudo relativo. Eu acredito que compara muito favoravelmente com bloqueio ponteiros inteligentes. Era uma parte importante de por que a equipe CLR escolheu verdadeira GC, em vez de algo usando contagem de referência. Consulte este artigo , em particular esta comparação gritante do que significa atribuição de referência se já contando acontecendo:

não ref contagem:

a = b;

contagem ref:

if (a != null)
    if (InterlockedDecrement(ref a.m_ref) == 0)
            a.FinalRelease();

if (b != null)
    InterlockedIncrement(ref b.m_ref);

a = b;

Se a própria instrução não é atômica, então você precisa para fazer a seção do código que atualiza a variável apropriada uma seção crítica.

i. Você necessidade de evitar que outros tópicos introduzidas nessa seção do código usando algum esquema de bloqueio. É claro que os bloqueios precisam ser atômica, mas você pode encontrar um mecanismo de bloqueio atômico dentro da classe pthread_mutex.

A questão da eficiência:. A biblioteca pthread é tão eficiente quanto possível e ainda garantir que o bloqueio mutex é atômica para o seu SO

É muito caro: Provavelmente. Mas, para tudo o que exige uma garantia de que há um custo.

Isso determinado código postado nesse artigo DDJ é aumentar a complexidade extra para conta para erros no uso de ponteiros inteligentes.

Especificamente, se você não pode garantir que o ponteiro inteligente não vai mudar em uma atribuição para outro ponteiro inteligente, você está fazendo errado ou estão fazendo algo muito pouco confiável para começar. Se o ponteiro inteligente pode mudar ao ser atribuído a outro ponteiro inteligente, que significa que o código está fazendo a tarefa não possui o ponteiro inteligente, que é suspeito para começar.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top