Que signifient atomic
et nonatomic
signifient les déclarations de propriété?
@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;
Quelle est la différence opérationnelle entre ces trois?
ios
objective-c
properties
atomic
nonatomic
Alex Wayne
la source
la source
Réponses:
Les deux derniers sont identiques; "atomic" est le comportement par défaut (
notez qu'il ne s'agit pas en fait d'un mot-clé; il n'est spécifié que par l'absence de- anonatomic
atomic
été ajouté comme mot-clé dans les versions récentes de llvm / clang).En supposant que vous synthétisez les implémentations de la méthode, atomique ou non atomique modifie le code généré. Si vous écrivez votre propre setter / getters, atomic / nonatomic / conserver / assigner / copier sont simplement consultatifs. (Remarque: @synthesize est désormais le comportement par défaut dans les versions récentes de LLVM. Il n'est pas non plus nécessaire de déclarer les variables d'instance; elles seront également synthétisées automatiquement et auront un
_
préfixe à leur nom pour empêcher tout accès direct accidentel).Avec "atomic", le setter / getter synthétisé s'assurera qu'une valeur entière est toujours retournée par le getter ou définie par le setter, quelle que soit l'activité du setter sur tout autre thread. Autrement dit, si le thread A se trouve au milieu du getter pendant que le thread B appelle le setter, une valeur viable réelle - un objet libéré automatiquement, très probablement - sera retournée à l'appelant en A.
En
nonatomic
, aucune garantie de ce type n'est offerte. Ainsi,nonatomic
est considérablement plus rapide que "atomique".Ce que "atomic" ne fait pas , c'est de garantir la sécurité des threads. Si le thread A appelle le getter simultanément avec les threads B et C appelant le setter avec des valeurs différentes, le thread A peut obtenir n'importe laquelle des trois valeurs renvoyées - celle qui précède l'appel des setters ou l'une des valeurs transmises aux setters en B et C. De même, l'objet peut se retrouver avec la valeur de B ou C, aucun moyen de le dire.
Garantir l'intégrité des données - l'un des principaux défis de la programmation multithread - est obtenu par d'autres moyens.
Ajoutant à cela:
atomicity
d'une seule propriété ne peut pas non plus garantir la sécurité des threads lorsque plusieurs propriétés dépendantes sont en jeu.Considérer:
Dans ce cas, le thread A pourrait renommer l'objet en appelant
setFirstName:
puis en appelantsetLastName:
. En attendant, le thread B peut appelerfullName
entre les deux appels du thread A et recevra le nouveau prénom couplé avec l'ancien nom de famille.Pour résoudre ce problème, vous avez besoin d'un modèle transactionnel . C'est-à-dire un autre type de synchronisation et / ou d'exclusion qui permet d'exclure l'accès
fullName
pendant la mise à jour des propriétés dépendantes.la source
@property NSArray* astronomicalEvents;
qui répertorie les données que je veux afficher dans l'interface utilisateur. Lorsque l'application lance le pointeur vers un tableau vide, l'application extrait des données du Web. Une fois la demande Web terminée (dans un autre thread), l'application crée un nouveau tableau, puis définit atomiquement la propriété sur une nouvelle valeur de pointeur. Il est sûr pour les threads et je n'ai pas eu à écrire de code de verrouillage, sauf s'il me manque quelque chose. Cela me semble assez utile.atomic
empêche les lectures de demi-valeur entre fils. (C'était un bug amusant à retrouver.)retain/autorelease
danse. Le thread B libère l'objet. Le fil A va boom .atomic
garantit que le thread A a une référence forte (un +1 retenir le nombre) pour la valeur de retour.Cela est expliqué dans la documentation d'Apple , mais voici quelques exemples de ce qui se passe réellement.
Notez qu'il n'y a pas de mot-clé "atomic", si vous ne spécifiez pas "nonatomic", alors la propriété est atomic, mais en spécifiant explicitement "atomic", vous obtiendrez une erreur.Si vous ne spécifiez pas "non atomique", la propriété est atomique, mais vous pouvez toujours spécifier "atomique" explicitement dans les versions récentes si vous le souhaitez.
Maintenant, la variante atomique est un peu plus compliquée:
Fondamentalement, la version atomique doit prendre un verrou afin de garantir la sécurité du thread, et est également en train de déplacer le compte de référence sur l'objet (et le compte de libération automatique pour l'équilibrer) afin que l'objet soit garanti pour l'appelant, sinon il y a est une condition de concurrence potentielle si un autre thread définit la valeur, entraînant la baisse du nombre de références à 0.
Il existe en fait un grand nombre de variantes différentes de la façon dont ces choses fonctionnent, selon que les propriétés sont des valeurs scalaires ou des objets, et comment interagissent la conservation, la copie, la lecture seule, la non-anatomique, etc. En général, les synthétiseurs de propriétés savent comment faire la "bonne chose" pour toutes les combinaisons.
la source
@property (assign) id delegate;
n'est synchronisé sur rien (iOS SDK GCC 4.2 ARM-Os
), ce qui signifie qu'il y a une course entre[self.delegate delegateMethod:self];
etfoo.delegate = nil; self.foo = nil; [super dealloc];
. Voir stackoverflow.com/questions/917884/…_val
/val
sont, mais non, pas vraiment. Le getter pour une propriété atomiccopy
/retain
doit s'assurer qu'il ne retourne pas un objet dont le refcount devient nul car le setter est appelé dans un autre thread, ce qui signifie essentiellement qu'il doit lire l'ivar, le conserver tout en s'assurant que le setter n'a pas écrasé et libéré, puis relâché automatiquement pour équilibrer la conservation. Cela signifie essentiellement que le getter et le setter doivent utiliser un verrou (si la disposition de la mémoire a été fixée, elle devrait être réalisable avec les instructions CAS2; hélas,-retain
c'est un appel de méthode).Atomique
Non atomique
la source
La meilleure façon de comprendre la différence est d'utiliser l'exemple suivant.
Supposons qu'il existe une propriété de chaîne atomique appelée "nom", et si vous appelez à
[self setName:@"A"]
partir du thread A, appelez à[self setName:@"B"]
partir du thread B et appelez à[self name]
partir du thread C, alors toutes les opérations sur différents threads seront effectuées en série, ce qui signifie si un thread exécute un setter ou getter, alors d'autres threads attendront.Cela rend la propriété "nom" en lecture / écriture sûre, mais si un autre thread, D, appelle
[name release]
simultanément, cette opération peut produire un crash car aucun appel setter / getter n'est impliqué ici. Ce qui signifie qu'un objet est protégé en lecture / écriture (ATOMIQUE), mais pas thread-safe car un autre thread peut envoyer simultanément tout type de messages à l'objet. Le développeur doit garantir la sécurité des threads pour ces objets.Si la propriété "nom" n'était pas atomique, alors tous les threads de l'exemple ci-dessus - A, B, C et D s'exécuteront simultanément produisant tout résultat imprévisible. En cas d'atome, l'un de A, B ou C s'exécutera en premier, mais D peut toujours s'exécuter en parallèle.
la source
La syntaxe et la sémantique sont déjà bien définies par d'autres excellentes réponses à cette question. Parce que l' exécution et les performances ne sont pas bien détaillées, j'ajouterai ma réponse.
J'avais toujours considéré l'atomique comme un défaut assez curieux. Au niveau de l'abstraction où nous travaillons, l'utilisation des propriétés atomiques pour une classe comme véhicule pour atteindre une sécurité de filetage à 100% est un cas d'angle. Pour des programmes multithreads vraiment corrects, l'intervention du programmeur est presque certainement une exigence. Pendant ce temps, les caractéristiques de performance et l'exécution n'ont pas encore été détaillées en détail. Après avoir écrit des programmes lourdement multithread au fil des ans, j'avais déclaré mes propriétés comme
nonatomic
tout le temps parce que l'atomique n'était pas sensé à quelque fin que ce soit. Au cours de la discussion des détails des propriétés atomiques et non anatomiques de cette question , j'ai fait du profilage rencontré quelques résultats curieux.Exécution
D'accord. La première chose que je voudrais clarifier est que l'implémentation de verrouillage est définie par l'implémentation et abstraite. Louis utilise
@synchronized(self)
dans son exemple - j'ai vu cela comme une source commune de confusion. La mise en œuvre ne fait utiliser@synchronized(self)
; il utilise des verrous rotatifs au niveau de l'objet . L'illustration de Louis est bonne pour une illustration de haut niveau utilisant des constructions que nous connaissons tous, mais il est important de savoir qu'elle n'utilise pas@synchronized(self)
.Une autre différence est que les propriétés atomiques conserveront / relâcheront le cycle de vos objets dans le getter.
Performance
Voici la partie intéressante: les performances utilisant des accès à la propriété atomique dans des cas non contestés (par exemple, un seul thread) peuvent être très rapides dans certains cas. Dans des cas moins qu'idéaux, l'utilisation des accès atomiques peut coûter plus de 20 fois les frais généraux de
nonatomic
. Alors que le cas contesté utilisant 7 threads était 44 fois plus lent pour la structure à trois octets (2,2 GHz Core i7 Quad Core, x86_64). La structure à trois octets est un exemple de propriété très lente.Note intéressante: les accesseurs définis par l'utilisateur de la structure à trois octets étaient 52 fois plus rapides que les accesseurs atomiques synthétisés; ou 84% de la vitesse des accessoires non anatomiques synthétisés.
Les objets dans les cas contestés peuvent également dépasser 50 fois.
En raison du nombre d'optimisations et de variations dans les implémentations, il est assez difficile de mesurer les impacts réels dans ces contextes. Vous pouvez souvent entendre quelque chose comme "Faites-lui confiance, à moins que vous ne vous fassiez un profil et que vous ne trouviez que c'est un problème". En raison du niveau d'abstraction, il est en fait assez difficile de mesurer l'impact réel. Glaner les coûts réels des profils peut prendre beaucoup de temps et, en raison des abstractions, être tout à fait inexact. De plus, ARC vs MRC peut faire une grande différence.
Revenons donc en arrière, ne nous concentrant pas sur la mise en œuvre des accès à la propriété, nous inclurons les suspects habituels comme
objc_msgSend
, et examinons certains résultats de haut niveau du monde réel pour de nombreux appels à unNSString
getter dans des cas non contestés (valeurs en secondes):Comme vous l'avez probablement deviné, l'activité / le cycle de comptage de référence est un contributeur important avec l'atomique et sous l'ARC. Vous verriez également de plus grandes différences dans les cas contestés.
Bien que je porte une attention particulière à la performance, je dis toujours la sémantique d'abord! . Pendant ce temps, la performance est une faible priorité pour de nombreux projets. Cependant, connaître les détails d'exécution et les coûts des technologies que vous utilisez ne fait certainement pas de mal. Vous devez utiliser la bonne technologie pour vos besoins, objectifs et capacités. J'espère que cela vous fera économiser quelques heures de comparaisons et vous aidera à prendre une décision plus éclairée lors de la conception de vos programmes.
la source
NSString
qui n'est pas immortel:-ARC atomic (BASELINE): 100% -ARC nonatomic, synthesised: 94% -ARC nonatomic, user defined: 86% -MRC nonatomic, user defined: 5% -MRC nonatomic, synthesised: 19% -MRC atomic: 102%
- les résultats sont un peu différents aujourd'hui. Je ne faisais aucune@synchronized
comparaison.@synchronized
est sémantiquement différent, et je ne le considère pas comme un bon outil si vous avez des programmes concurrents non triviaux. si vous avez besoin de vitesse, évitez@synchronized
.Atomic = sécurité des threads
Non atomique = Aucune sécurité de filetage
Sécurité du fil:
Les variables d'instance sont thread-safe si elles se comportent correctement lorsqu'elles sont accessibles à partir de plusieurs threads, indépendamment de la planification ou de l'entrelacement de l'exécution de ces threads par l'environnement d'exécution, et sans synchronisation supplémentaire ou autre coordination de la part du code appelant.
Dans notre contexte:
Si un thread modifie la valeur de l'instance, la valeur modifiée est disponible pour tous les threads et un seul thread peut modifier la valeur à la fois.
Où utiliser
atomic
:si la variable d'instance est accessible dans un environnement multithread.
Implication de
atomic
:Pas aussi vite que
nonatomic
parcenonatomic
qu'il ne nécessite aucun travail de surveillance sur ce point à partir de l'exécution.Où utiliser
nonatomic
:Si la variable d'instance ne va pas être modifiée par plusieurs threads, vous pouvez l'utiliser. Il améliore les performances.
la source
J'ai trouvé une explication assez bien définie des propriétés atomiques et non atomiques ici . Voici un texte pertinent de la même:
Parce que les
atomic
variables ne peuvent pas être interrompues, la valeur qu'elles contiennent à tout moment est (thread-lock) garantie d'être non corrompue , bien que, en s'assurant que ce verrou de thread rend l'accès à elles plus lent.non-atomic
les variables, d'autre part, n'offrent pas une telle garantie mais offrent le luxe d'un accès plus rapide. Pour résumer, continueznon-atomic
lorsque vous savez que vos variables ne seront pas accessibles simultanément par plusieurs threads et accélérez les choses.la source
Après avoir lu tant d'articles, publié des articles sur Stack Overflow et créé des applications de démonstration pour vérifier les attributs des propriétés variables, j'ai décidé de rassembler toutes les informations sur les attributs:
atomic
// Défautnonatomic
strong = retain
// Défautweak = unsafe_unretained
retain
assign
// Défautunsafe_unretained
copy
readonly
readwrite
// DéfautDans l'article Attributs de propriété variable ou modificateurs dans iOS, vous pouvez trouver tous les attributs mentionnés ci-dessus, et cela vous aidera certainement.
atomic
atomic
signifie qu'un seul thread accède à la variable (type statique).atomic
est thread-safe.atomic
est le comportement par défautExemple:
nonatomic
nonatomic
signifie que plusieurs threads accèdent à la variable (type dynamique).nonatomic
est thread-unsafe.nonatomic
n'est PAS un comportement par défaut. Nous devons ajouter lenonatomic
mot - clé dans l'attribut de propriété.Exemple:
la source
Atomique:
Atomic garantit que l'accès à la propriété se fera de manière atomique. Par exemple, il retourne toujours des objets entièrement initialisés, tout get / set d'une propriété sur un thread doit se terminer avant qu'un autre puisse y accéder.
Si vous imaginez la fonction suivante se produire sur deux threads à la fois, vous pouvez voir pourquoi les résultats ne seraient pas jolis.
Avantages: Le retour d'objets entièrement initialisés à chaque fois en fait le meilleur choix en cas de multi-threading.
Inconvénients: Performance hit, rend l'exécution un peu plus lente
Non atomique:
Contrairement à Atomic, il ne garantit pas à chaque fois un retour d'objet complètement initialisé.
Avantages: exécution extrêmement rapide.
Inconvénients: Chances de valeur de déchets en cas de multi-threading.
la source
Réponse la plus simple en premier: il n'y a pas de différence entre vos deux seconds exemples. Par défaut, les accesseurs de propriété sont atomiques.
Les accesseurs atomiques dans un environnement non récupéré (c.-à-d. Lors de l'utilisation de retenue / libération / libération automatique) utiliseront un verrou pour garantir qu'un autre thread n'interfère pas avec le bon réglage / obtention de la valeur.
Consultez la section " Performances et threading " de la documentation Objective-C 2.0 d'Apple pour plus d'informations et pour d'autres considérations lors de la création d'applications multi-thread.
la source
Atomic signifie qu'un seul thread accède à la variable (type statique). Atomic est thread-safe, mais il est lent.
Non anatomique signifie que plusieurs threads accèdent à la variable (type dynamique). Nonatomic n'est pas sûr pour les threads, mais il est rapide.
la source
Atomic est thread-safe , il est lent et il assure bien (non garanti) que seule la valeur verrouillée est fournie quel que soit le nombre de threads tentant d'accéder sur la même zone. Lorsque vous utilisez atomic, un morceau de code écrit à l'intérieur de cette fonction devient la partie de la section critique, à laquelle un seul thread peut s'exécuter à la fois.
Il assure seulement la sécurité du fil; cela ne garantit pas cela.Ce que je veux dire, c'est que vous louez un chauffeur expert pour votre voiture, mais cela ne garantit pas que la voiture ne rencontrera pas d'accident. Cependant, la probabilité reste la plus faible.
Atomique - il ne peut pas être décomposé, donc le résultat est attendu. Avec nonatomic - lorsqu'un autre thread accède à la zone mémoire, il peut le modifier, donc le résultat est inattendu.
Code Talk:
Atomic sécurise le getter et le setter du thread de propriété. par exemple si vous avez écrit:
est thread-safe.
n'est PAS sûr pour les threads.
la source
Il n'y a pas un tel mot-clé "atomique"
Nous pouvons utiliser ce qui précède comme
Voir la question Stack Overflow Je rencontre des problèmes si j'utilise @property (atomic, retenue) NSString * myString .
la source
Voir plus ici: https://realm.io/news/tmi-objective-c-property-attributes/
la source
La valeur par défaut est
atomic
, cela signifie que cela vous coûte des performances chaque fois que vous utilisez la propriété, mais elle est thread-safe. Ce que fait Objective-C, c'est de définir un verrou, de sorte que seul le thread réel peut accéder à la variable, tant que le setter / getter est exécuté.Exemple avec MRC d'une propriété avec un ivar _internal:
Ces deux derniers sont donc les mêmes:
En revanche,
nonatomic
n'ajoute rien à votre code. Il n'est donc sûr que si vous codez vous-même le mécanisme de sécurité.Il n'est pas nécessaire que les mots clés soient écrits comme premier attribut de propriété.
N'oubliez pas, cela ne signifie pas que la propriété dans son ensemble est thread-safe. Seul l'appel de méthode du setter / getter l'est. Mais si vous utilisez un setter et ensuite un getter en même temps avec 2 threads différents, cela pourrait aussi être cassé!
la source
Avant de commencer: Vous devez savoir que chaque objet en mémoire doit être désalloué de la mémoire pour qu'un nouvel écrivain se produise. Vous ne pouvez pas simplement écrire sur quelque chose comme vous le faites sur papier. Vous devez d' abord l'effacer (désallouer) et ensuite vous pouvez y écrire. Si au moment où l'effacement est fait (ou à moitié fait) et que rien n'a encore été écrit (ou à moitié écrit) et que vous essayez de le lire, cela pourrait être très problématique! Atomic et nonatomic vous aident à traiter ce problème de différentes manières.
Lisez d'abord cette question, puis lisez la réponse de Bbum . De plus, lisez mon résumé.
atomic
garantira TOUJOURSQuoi?! Le multithreading et la sécurité des threads sont-ils différents?
Oui. Le multithreading signifie: plusieurs threads peuvent lire une donnée partagée en même temps et nous ne nous bloquerons pas, mais cela ne garantit pas que vous ne lisez pas à partir d'une valeur non publiée automatiquement. Avec la sécurité des threads, il est garanti que ce que vous lisez n'est pas publié automatiquement. La raison pour laquelle nous ne rendons pas tout atomique par défaut est qu'il y a un coût de performance et pour la plupart des choses, nous n'avons pas vraiment besoin de sécurité des threads. Quelques parties de notre code en ont besoin et pour ces quelques parties, nous devons écrire notre code de manière thread-safe à l'aide de verrous, de mutex ou de synchronisation.
nonatomic
Globalement, ils sont différents sous 2 aspects:
Plantage ou non en raison de la présence ou non d'un pool de libération automatique.
Permettre d'être lu en plein milieu d'une «écriture pas encore terminée ou d'une valeur vide» ou ne pas autoriser et autoriser la lecture uniquement lorsque la valeur est entièrement écrite.
la source
Si vous utilisez votre propriété dans du code multithread, vous pourrez voir la différence entre les attributs non atomiques et atomiques. Nonatomic est plus rapide qu'atomic et atomic est thread-safe, pas nonatomic.
Vijayendra Tripathi a déjà donné un exemple pour un environnement multi-thread.
la source
Comment déclarer:
Comme atomic est par défaut,
ET dans le fichier d'implémentation
Supposons qu'une tâche liée à trois propriétés soit
Toutes les propriétés fonctionnent en parallèle (comme de manière asynchrone).
Si vous appelez "nom" à partir du thread A ,
Et
En même temps, si vous appelez
du fil B ,
Si maintenant la propriété de nom * est nonatomic alors
C'est pourquoi non atomique est appelé thread dangereux, mais ses performances sont rapides en raison de l'exécution parallèle
Maintenant, si la propriété * name est atomique
Voilà pourquoi atomic est appelé thread Safe et c'est pourquoi il est appelé lecture-écriture safe
Une telle opération de situation fonctionnera en série. Et lent dans les performances
- Nonatomique signifie que plusieurs threads accèdent à la variable (type dynamique).
- Nonatomic est dangereux pour les threads.
- mais ses performances sont rapides
-Nonatomic n'est PAS un comportement par défaut, nous devons ajouter un mot-clé nonatomic dans l'attribut de propriété.
Pour In Swift Confirmer que les propriétés Swift ne sont pas anatomiques au sens ObjC. L'une des raisons est que vous vous demandez si l'atomicité par propriété est suffisante pour vos besoins.
Référence: https://forums.developer.apple.com/thread/25642
Pour plus d'informations, veuillez visiter le site Web http://rdcworld-iphone.blogspot.in/2012/12/variable-property-attributes-or.html
la source
atomic
n'est PAS du thread-safe! Il est plus résistant aux problèmes de threads, mais pas thread-safe. Il garantit simplement que vous obtiendrez une valeur entière, alias une valeur "correcte" (niveau binaire), mais en aucun cas, il garantira qu'il s'agit de la valeur actuelle et "correcte" pour votre logique métier (il pourrait s'agir d'une valeur passée et invalide par votre logique).Atomicité atomique (par défaut)
non anatomique
courtoisie https://academy.realm.io/posts/tmi-objective-c-property-attributes/
Les attributs de propriété d'atomicité (atomique et non atomique) ne sont pas reflétés dans la déclaration de propriété Swift correspondante, mais les garanties d'atomicité de l'implémentation d'Objective-C restent valables lorsque la propriété importée est accessible à partir de Swift.
Donc - si vous définissez une propriété atomique dans Objective-C, elle restera atomique lorsqu'elle sera utilisée par Swift.
courtoisie https://medium.com/@YogevSitton/atomic-vs-non-atomic-properties-crash-course-d11c23f4366c
la source
La propriété atomique garantit de conserver une valeur entièrement initialisée quel que soit le nombre de threads exécutant getter et setter dessus.
La propriété nonatomique spécifie que les accesseurs synthétisés définissent ou retournent simplement une valeur directement, sans aucune garantie de ce qui se passe si cette même valeur est accédée simultanément à partir de différents threads.
la source
Atomic signifie qu'un seul thread peut accéder à la variable à la fois (type statique). Atomic est thread-safe, mais il est lent.
Non anatomique signifie que plusieurs threads peuvent accéder à la variable en même temps (type dynamique). Nonatomic n'est pas sûr pour les threads, mais il est rapide.
la source
Si vous utilisez atomic, cela signifie que le thread sera sûr et en lecture seule. Si vous utilisez non anatomique, cela signifie que les threads multiples accèdent à la variable et que le thread n'est pas sûr, mais il est exécuté rapidement, fait des opérations de lecture et d'écriture; c'est un type dynamique.
la source
La vérité est qu'ils utilisent le verrouillage par rotation pour implémenter la propriété atomique. Le code comme ci-dessous:
la source
Pour simplifier toute la confusion, comprenons le verrouillage mutex.
Le verrouillage Mutex, selon le nom, verrouille la mutabilité de l'objet. Donc, si l'objet est accessible par une classe, aucune autre classe ne peut accéder au même objet.
Dans iOS,
@sychronise
fournit également le verrou mutex. Maintenant, il sert en mode FIFO et garantit que le flux n'est pas affecté par deux classes partageant la même instance. Cependant, si la tâche se trouve sur le thread principal, évitez d'accéder à l'objet à l'aide des propriétés atomiques car il peut contenir votre interface utilisateur et dégrader les performances.la source
Atomic: assurez la sécurité du fil en verrouillant le fil à l'aide de NSLOCK.
Non atomique: n'assure pas la sécurité du fil car il n'y a pas de mécanisme de verrouillage du fil.
la source
Propriétés atomiques : - Lorsqu'une variable affectée avec une propriété atomique qui signifie qu'elle n'a qu'un accès au thread et qu'elle sera sûre pour les threads et sera bonne en termes de performances, aura un comportement par défaut.
Propriétés non atomiques : - Lorsqu'une variable affectée avec une propriété atomique signifie qu'elle a un accès multi-thread et qu'elle ne sera pas thread-safe et sera lente dans la perspective des performances, aura un comportement par défaut et lorsque deux threads différents veulent accéder à la variable en même temps cela donnera des résultats inattendus.
la source