Question

Je veux vérifier que je comprends bien. Ce genre de chose est délicate, donc je suis presque sûr que je manque quelque chose. J'ai un programme composé d'un fil en temps réel et un fil en temps non réel. Je veux que le fil non-RT pour pouvoir échanger un pointeur vers la mémoire qui est utilisée par le fil RT.

De la documentation, je crois comprendre que cela peut être accompli en g++ avec:

// 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;
}

Ceci est le seul endroit dans le programme (autre que la configuration initiale) où rt_data est modifié. Lorsque rt_data est utilisé dans le contexte en temps réel, il est copié dans un pointeur local. Pour old_d, plus tard quand il est sûr que la vieille mémoire n'est pas utilisé, il sera libéré dans le fil non-RT. Est-ce correct? Ai-je besoin volatile partout? Y at-il d'autres primitives de synchronisation j'appellerez?

Par la façon dont je fais cela en C ++, bien que je suis intéressé à savoir si la réponse est différente C.

Merci à l'avance.

Autres conseils

Mise à jour : Cette réponse est incorrecte, car je manque le fait que les garanties de volatile que les accès aux volatile variables ne sont pas réorganisées, mais ne fournit aucune de ces garanties par rapport aux autres non-volatile accès et manipulations. Une clôture de mémoire fournit de telles garanties, et est nécessaire pour cette application. Ma réponse originale est ci-dessous, mais ne pas agir sur elle. Voir cette réponse pour une bonne explication dans le trou dans ma compréhension qui a conduit à la mauvaise réponse suivante.

Réponse originale:

Oui, vous avez besoin volatile sur votre déclaration de rt_data; tout moment une variable peut être modifiée en dehors du flux de contrôle d'un fil d'y accéder, il doit être déclaré volatile . Alors que vous pourriez être en mesure de sortir sans volatile puisque vous copiez un pointeur local, volatile aide au moins avec la documentation et inhibe également certaines optimisations du compilateur qui peuvent causer des problèmes. Prenons l'exemple suivant, adopté de DDJ :

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

S'il est possible d'avoir a sa valeur a changé entre a=1 et b=a, alors a devrait être déclarée volatile (à moins, bien sûr, l'attribution d'une valeur hors-date b est acceptable). Multithreading, en particulier avec des primitives atomiques, constitue une telle situation. La situation est également déclenchée avec des variables modifiées par des gestionnaires de signaux et par des variables mises en correspondance avec des emplacements de mémoire impaires (par exemple des registres d'entrée / sortie hardware). Voir aussi cette question.

Dans le cas contraire, il semble bien pour moi.

En C, je serais probablement utiliser les primitives atomiques fournies par GLib pour cela. Ils utilisent une opération atomique si disponible et se replient à un déploiement en mutex lente mais correcte si les opérations atomiques ne sont pas disponibles. Boost peut fournir quelque chose de similaire pour C ++.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top