Pergunta

Eu quero verificar se meu entendimento está correto.Esse tipo de coisa é complicado, então eu tenho quase certeza que eu estou faltando alguma coisa.Eu tenho um programa que consiste em uma thread em tempo real e um não-tempo-real thread.Eu quero que o não-RT thread para ser capaz de trocar um ponteiro para a memória que é utilizada pelo RT thread.

A partir do google docs, o meu entendimento é que isso pode ser feito em g++ com:

// global
Data *rt_data;

Data *swap_data(Data *new_data)
{
#ifdef __GNUC__
    // Atomic pointer swap.
    Data *old_d = __sync_lock_test_and_set(&rt_data, new_data);
#else
    // Non-atomic, cross your fingers.                                          
    Data *old_d = rt_data;
    rt_data = new_data;
#endif
    return old_d;
}

Este é o único lugar no programa (que a configuração inicial) onde rt_data é modificado.Quando rt_data é usado em tempo real contexto, ele é copiado para um local do ponteiro.Para old_d, e , mais tarde, quando é certo que a memória antiga não é usado, ele será libertado, o não-RT thread.Isso está correto?Eu preciso volatile em qualquer lugar?Existem outros primitivos de sincronização eu deveria ser chamado?

Pelo jeito que eu estou fazendo isso em C++, embora eu estou interessado em saber se a resposta é diferente para C.

Graças antes do tempo.

Foi útil?

Solução

Geralmente não usa volatile Ao escrever código simultâneo em C/C++. A semântica de volatile estão tão próximos do que você quer que seja tentador, mas no final é volátil insuficiente. Infelizmente Java/C# volatile != C/C++ volatile. Herb Sutter tem um ótimo artigo explicando a bagunça confusa.

O que você realmente quer é uma cerca de memória. __sync_lock_test_and_set fornece a esgrima para você.

Você também precisará de uma cerca de memória quando copiar (carregar) o ponteiro RT_Data para a sua cópia local.

A programação livre de bloqueio é complicada. Se você estiver disposto a usar as extensões C ++ 0x do GCC, é um pouco mais fácil:

#include <cstdatomic>

std::atomic<Data*> rt_data;

Data* swap_data( Data* new_data )
{
   Data* old_data = rt_data.exchange(new_data);
   assert( old_data != new_data );
   return old_data;
}

void use_data( )
{
   Data* local = rt_data.load();
   /* ... */
}

Outras dicas

Atualização:Esta resposta não é correta, como eu estou faltando o fato de que volatile garante que acessos volatile variáveis não são reordenadas, mas não fornece tais garantias com respeito a outras nãovolatile acessos e manipulações.Uma memória de cerca de fornecer tais garantias, o que é necessário para esta aplicação.Minha resposta original está abaixo, mas não agem sobre ele.Ver esta resposta para uma boa explicação para o buraco em meu entendimento que levou à seguinte resposta incorreta.

Original resposta:

Sim, você precisa volatile no seu rt_data declaração; sempre que uma variável pode ser modificada fora o fluxo de controle de um thread acessando, ele deve ser declarado volatile.Enquanto você pode ser capaz de fugir sem volatile uma vez que você está copiando para um local do ponteiro, volatile pelo menos ajuda com a documentação e também inibe algumas otimizações do compilador que pode causar problemas.Considere o seguinte exemplo, adotado a partir de DDJ:

volatile int a;
int b;
a = 1;
b = a;

Se for possível, para a para ter seu valor alterado entre a=1 e b=a, e , em seguida, a deve ser declarado volatile (a menos, é claro, atribuir um valor de data para b é aceitável).Multithreading, particularmente com o atomic primitivos, constitui uma situação como essa.A situação também é acionado com variáveis modificadas por sinal manipuladores e por variáveis mapeadas ímpar locais de memória (por exemplo,hardware registradores de e/S).Veja também esta pergunta.

Caso contrário, parece-me muito bem.

Em C, eu provavelmente usaria o atomic primitivos fornecida pela GLib para este.Eles vão usar uma operação atômica, onde disponível e cair de volta para uma lenta, mas correto mutex-com base em implementação se as operações atômicas não estão disponíveis.Impulso pode fornecer algo semelhante para C++.

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