Files
boc/aamos-ledger-rust/target/debug/deps/libarc_swap-d727bbe9fe4f9b82.rmeta
T

735 lines
315 KiB
Plaintext
Raw Normal View History

rust
#rustc 1.96.0 (ac68faa20 2026-05-25)ÁÀ뉊]!ÜÛê(¹Þ—šên-5be7b69c3ff7b5b8ÁíàÄTËŸ ÜJîÄ)'ß\¥!-3d1337db07d0b3aeÁ¤²XctÔ'ÐÓ©z¨ɽÓ-a4945860e1c53b00Á¤°ð ¾ä-±($²ï=©Ã-7e98a21bfd32b0edÁòÖÀH•‘PIÓHã#£-055f30b747f859b6Árustc_std_workspace_coreÁ­Cçß^ò½èÝ$­Çÿ+Cé-c4878ee60b2242c9ÁŸÃï+Ñ]ŠqB<ÏïW#-8dd1dd90e70d0b6aÁ miniz_oxideÁ€š»J(P>àö÷g\K-1eb618da2918ab7fÁadler2ÁÆ;+Þ®5¥Ìýݰ¦ÛLˆ-f7919172d268e069Á hashbrownÁPäV9ÒÆèÜ"ÊÖVŽ\-0fc2184a5da6723aÁrustc_std_workspace_allocÁs&ØòØy¯s•bæ!‰ýŠ-97e4bf30be240674Á
std_detectÁhŠBîÙºÌI®ËÅš-9dbbf8346ba7ac8bÁrustc_demangleÁûë9´Ç×@Œ’ùXFº-f33013f239bf9f14Ácfg_ifÁÜLhž§Œaã¯>­-0a71c8f33a838301Á addr2lineÁ׎Þ!]8V$É@@-e618e6be60e87ba2ÁgimliÁ¸
°µ~Î1‹Ñt ðÁ€w-1f7768a68858f670ÁobjectÁ
áPÃ?­À¶¼QHJ¥-914cd6a4dbe590d1ÁmemchrÁ›º«8Ór­2Ù $¨ûib-cf21ca6f2bb15dcdÁë
‹ás«LÖ€îâƒ×ɯŒ-ee6f3747e38367f0Á rustversionÁTgÌüÁé¨Cå@Ö'G-f0da710c68354185ÁtestsÁ,Ý[$Ò[ù,ÅF$ºFíOnceCellÁD‡ »experimental-thread-localÁüÏ %í THREAD_HEADÁ\»e»ºüÓd%íù,f$öe¼ù,&$€&Áù,X$…XserdeÁ,ä-»½ ŒÌ-àrw_lockÁ<ô»internal-test-strategiesÁüÉ$àtest_strategiesÁ|ê»ì ü¬$Ü$š.»Ü„ƒ. ArcSwapWeakÁ\©å»Üåinternal_strategiesÁœñõ»ì üªõ$ù,Æ÷$»÷
tests_defaultÁlÿô £æÀaccessÁ 
AccessÁ¥GuardÁ¬¥¡° ¬¥° ¬¥° ¬!¥!° !¬%¥%¤%° %¬*¥*¤*å*´/¥/¤/° /¬4¥4¤4å4´9¥9¤9° 9¬DynGuardÁ>
>¥>ˆ B¥BåB´ DynAccessÁF¥F¬
I¥II¬
AccessConvertÁM
MMˆ Q¥QQ° Q¬ V˜VV¥V£VåV´
]]¥]]æ a£ccc¥c£c° c¬j¥jåj´n¥n° n¬as_rawÁrrrrsealedÁvSealedÁrrAsRawÁy¥yÁr|¥r~¥~Ár¥rƒ¥ƒÁr¥rˆ¥ˆÁr¥r¥Ár¥r ¥ÁcacheÁœ ¥¬žž¥ž¤žæ žarc_swapÁž¬žload_no_revalidateÁž
revalidateÁžØ§§¦ªª¥ª¤ª¬¯¯¥¯¤¯÷´´¥´¤´´¦´¬compile_fail_testsÁdebtÁ¼¼¼¼¼¼¼fastÁÃÃÃÃÃ
DEBT_SLOT_CNTÁÃÉget_debtÁÃË'aÁËËIntoIterÁËê¼helpingÁÐÐÐÐÐÐÐÐÐREPLACEMENT_TAGÁÐGEN_TAGÁÐTAG_MASKÁÐIDLEÁÐSlotsÁÝcontrolÁÝslotÁÝ active_addrÁÝhandoverÁÝ space_offerÁÐã>Ðå½åéåhelpÁè£è¥åinitÁåconfirmÁ¼listÁíííííííííí í
í í í
ííí NODE_UNUSEDÁí NODE_USEDÁí
NODE_COOLDOWNÁí LIST_HEADÁíNodeReservationÁ
þˆíãíNodeÁˆ¯ˆ¨ˆin_useÁˆó ˆactive_writersÁíŽ>ítraverseÁ£start_cooldownÁcheck_cooldownÁreserve_writerÁgetÁ  
fast_slotsÁ helping_slotÁí LocalNodeÁœnodeÁœ¯œ¨í withÁ¡£¡¡ ¡  new_fastÁ  new_helpingÁ confirm_helpingÁ¨ ¨   «£«¥í®ã¼°NONEÁ¼²>¼´payÁµ¥´pay_allÁ·¥·£· º docsÁ¼å¼ limitationsÁ¼patternsÁ¼ performanceÁref_cntÁÁÁÁÁÁÁRefCntÁÇBaseÁÇinto_ptrÁÇas_ptrÁÇfrom_ptrÁÇincÁÇdecÁÁÎ¥ÎÉ ÎÕ Îå Îó ÁÔ¥ÔÉ ÔÕ Ôå Ôó ÁÚ¥ÚÉ ÚÕ Úå Úó strategyÁààààhybridÁääääääääää ä
ä ä ä
äääHybridProtectionÁõ¥õõµ äù¥ùæ ùattemptÁù¸ùå äÿ¥ÿãä¥
from_innerÁ
into_innerÁä¥borrowÁäConfigÁUSE_FASTÁäï$ä¥CfgÁ ProtectedÁ¬  wait_for_readersÁ 䥙%compare_and_swapÁààààDefaultStrategyÁàIndependentStrategyÁàÚ   ¤%£¥£´$£¢$ 
InnerStrategyÁ§¥§¤%§¬§Ç% CaSÁ¬¥¬ù%®àStrategyÁ°¥à²¥²¤àÁ'µ¥à·¥·¤importsÁ 
  
° ٥٤ÙinnerÁݥݤݴ$Ý¢$â¥â¤âåâ´ç¥ç¤ç÷ë¥ë¤ë>ï¥ï¤ï×ó¥ó¤ó×ptr_eqÁ÷É ÷÷
ArcSwapAnyÁû¥û¤ûµ û _phantom_arcÁûŸ"¥¤÷¥¤ã¥¤× ¥¤×
¥¤> ¥¤æ 
with_strategyÁ´$ load_fullÁ¬ÈswapÁù%ŸrcuÁ¡£¡Ø¤š¤£¤ArcSwapÁ¨¥ ª¥ª¤ª from_pointeeÁ
ArcSwapOption稴
°¥°¤°ç.³§°emptyÁ¥ const_emptyÁIndependentArcSwapÁ¹¥¿¤ DirectDerefÁ½
½¥½¤½ˆÂ¥Â¤Â×MapGuardÁÆ˜ÆÆ¥Æ£Æ£Æ
projectionÁÆýΘÎΥΣӘÓÓ¥Ó£ÓƒÙ˜Ù٥٣Ù×MapÁßߥßßã ߘ1ßýææ¥æêê¥êêƒïï¥ïï×
ConstantDerefÁô
ô¥ôˆø¥ú¥úƒý¥ý×¥Öƒ¥¥ˆ¥ˆ¥ï
 ޥާùConstantÁ
¥ˆ!¥"˜¥˜ƒ#¥×$ž¥žÖ%¡¥&£¥£'¦¥¦(©¥©ï
)¬¥¬§®ùCacheÁ°°¥°°cachedÁµµ¥µƒ¹¹¥¹×MapCacheÁ½½¥½½Ó)½˜1ÃÃ¥ÃÃÈÈ¥ÈÈ×ÃLocalÁÍž
ÃÏ>áÑ
ÑˆÓ ÃÕ>Ðà8×
generationÁÐÙ>ÐHandoverÁÛ
ÛˆÐÞ>íßà__rust_std_internal_init_fnÁà â ã__RUST_STD_INTERNAL_VALÁâ å«:¼DebtÁç
爼ê×ÁÁí¥íÉ íÕ íå íó Áó¥óÉ óÕ óå óó ä
DefaultConfigÁù
äûƒäý>äHybridStrategyÁÿ™%ÿ_configÁä ™%ƒä
™%>ºººº





!
$
)
.
3
8
=
E
H
L
U
V
\
a
c
i
m
q
{
|
~


ƒ

Š



£
¤
¥
¦
§
®
´
º
Ê
Ê
æ
ç
ç
è
è
è
ë
ì





š

¡
¦
§
¨
«
«
«
¯
µ
Ê
Ì
Ò
Ø
Þ
ü
ü
ý
ý
þ

ˆ






ª
ª
«
«
®
®
æ
ò
ò
ò
ö
ö
ö
ˆ
Œ
Œ
Œ




œ

ž
Ÿ
¡
¡
¤
¤
Å
Å
Å
Æ
Ø
Þ
Þ
Þ
î
ó
ó
ó
ü
ÿ
ÿ
ÿ



Š
Š




š



 
¥
¥
¨
¨
«
«
®
®
¸
¼
¼
¼
Ç
Ì
Ì
Ì
ë
ë
ë
ñ
÷
ü

Fwy›Ç£§¬°µ¡¥F¥8ØDFØDÌì8ØDFØD Ìì8ØDûû»+þµ ÿå+Ÿ"ë§oŽB‹ÄD¤ÄD¿c½½¾•0Áˆ PzèýuÄDòEé!½½¾•0Áˆ Pzèýu†J†JK‰Jµ 7ŠJphantomÁ7J¤7·0ØQdèÄDçEçEèEGlobalÁ ¿±‡§í#òEûû»+þµ ÿå+Ÿ"ë§oŽB‹ñFòEÄDé!½½¾•0Áˆ PzèýuòHòHÆõHµ Ñ,öHFÑ,÷H¤Ñ,+átLaû§ÄDÀGòEûû»+þµ ÿå+Ÿ"ë§oŽB‹ùHòEÄDé!>>?ÕAˆ âù&ÄDFÄDMMNÆPˆ á³æÇ—†¹‘ÄDŠ ÆÆà0ˣ̘1Íýæ:óFŸ‰`˜¥£Ø¡K¿c¡Ké!¡KŠ ßß­2ãã ä˜1åý±ìi0Â% ØDØ¡L¿c¡Lßß­2ãã ä˜1åý±ìi0Â% äLðKêKöKŠ ôôõË3÷ˆ p²1=ÃHÄDØãM¿cãMãMÐìãMµßãMãMºãMíßãMãMšeãMé!ãMŠ  5ˆ ìXN#£¤¬ÄDØO¿cOOÐìOµßOOºOíßOOšeOOÄDw 8ØDyžPØDÈw 8ÙÙ° ÜÓ)Ù¡âßñ:¢ØDÿÿ<­<8öÞÃP›lùùúÜ; Õì4õ´\)yÀP°PwÙÙ° ÜÓ)Ù¡âßñ:¢ÄDõPyÛQÄDÈw ÄDy§RÄDw ÄDy¾RÄDذ°ñ6³´–7
ê ·zäLØD¿cÖRÖRØDê!éÖRäLؽ½Þ7ÁÓ)˜1ùœ"‡²Vð5äLØDíL¿cÈS½½Þ7ÁÓ)˜1ùœ"‡²Vð5äLØD¦³ÍÍà8Ξ
Ã݉™cªƒ³ÑÑҡӈà ¹Þm8–sÇL þ¤U³××à8د9иDoº-1³ÛÛÜÍ9݈Рôò±À˜9 £³ÝݡޮÐß½ÐàÉÐáÜÐâìÐâyU=øžŒ"ƒýˆí AWÍÀ£¾k~8³ˆˆ¯íЍíÒíŒó íèí¬f{ÞgÚŒ"œœ¬½íž¯íŸ¨íc7û‘„<[¿cççè×:éˆ Í€™Cö³³YÇñFÇùHÇÛ¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙÄDÇ„¾„¾PinÁ†¾ ˜X$]È=„kt•ñFÇ„¾„¾äY†¾ ˜X$]È=„kt•ùHŒ"õõœ#÷äøµ ä¹Òóû÷O¡ÄD£Ñ[ÄD Ñ[ÄDØ¢Q³¢Q¢QØÿÿ<­<8öÞÃP›l™%³Í\§ÿÿ<­<8öÞÃP›l™%ÄD¬‘]ÄD°òEÄDµòEÄDé!ÙÙ° ÜÓ)Ù¡âßñ:¢ÄDòEéõ]ÄD³õ]¿cõ]Äcõ]é¬EÄDŒ"¬E¿c¬EÄc¬E³¬EFF!F%û/û9ûQMcßnÂ½ÙÆïßýô¹°È½êçïÙû*½4½B>VÆjôâÙIÎÆæßøôÓÆêßúô˜µ°Ã½ûùÿôžƒô¡ô£ˆô¦ô©Žô¬|

Ù  ~
ƒ
ˆÙ  ª°´½¯°çÙûÏÍÕÑÙ×ÞÛãÝŽˆ²çýùÿëÙûË
®œÿõûΆJÔòHÚۼ턾ó„¾õõùÿÿ²·óÙû
ê¿c
4é!FF$Š Ø8Ðìµßºíßšewyé³ ÇLMŒ"Ç£& §¬°µÄce
DEBT_SLOT_CNTÁe0b01Áe0b10Áe0b11Áe‹e‹e‹eùj·e

éj·e
¾æXùjÕúeâÛ¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙ Û¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙæX æX€g±ßùifaà®®£°Ó)¨it§ÅLS¶æXái¢faXâ€g€gùjðe
éjðe
ÐæX/5ùj¦®e  ã…g˜h/€g j¿eùjíÔeùj‚!­e  å‡jŠj™j#€g j!eM jÀ$eùjÛôeâ€gã‡jŠj™jåå‡jŠj™jŸSe0b11ÁtrueÁüØÜ|çÜ
lçÜ
²ÄD,:
AtØÜ
Ò]ÄDQc öÜ\“Ý  Û¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙñFü¶ÝFlàÝ  ù$ ÿ¢Q ûÝüÀÜÇ û®mõP †Þ Þ¸ü“Üúûû»+þµ ÿå+Ÿ"ë§oŽB‹®mõP$±Ü¤]¤]V¦]Á‚]üß3ø¤”&§Rñ§Rï PhantomDataÁFu\»Ÿ®mÂõPh¢Qfæü¶*1 ½ÄDòE¾,F7õ]>Eô§0 >ÄD?&¡J1žBoxÁ¡ˆˆ¢ˆl }.xÏé!ê!ÄDÀGŒܸD MN)MMNÆPˆ á³æÇ—†¹‘s_sfmÜ´U ôÄDõ(ãM3ÄD:A´‹Z ÄD(O3ÄD:A¼ì
 ÑÒ%¤U0³YeEL|9 ÛÜ%£V0¤]¤]V¦]Á‚]üß3ø¤”&edkô— ƒ'ƒýˆí AWÍÀ£¾k~c €Xmt´ˆ çè%³Y0™v7>r•»¼¼ÁàºÙ÷û¨®¹ÀY4ê0 »p,1¿c½pÂc½t<‰1Äc¾ˆL1 c¿ FmtResultÁL§1ébÀ³o\Å1Á³oÁíÜ1ëÂr,ð1é!õ 2Ä AtomicPtrÁLŸ2¯]Æ®Dª2¼ÀÇKÊ2†JÈœ 4ä2Ê­2ì2ßËø,‰3yÌñ6,¦3°Í» 4Å3ÇÎÜ;lë3ùÐÜ;úÐ<tú3ÿѤ%L¨4£ÒÁ'É4µÔä'DÎ4°Õ¨&|ó4ž×¿&œ„5ŸØ¤,Ö,¼ü¾‹ü€  Making [`Arc`] itself atomicÁ¡úü¥b_ The [`ArcSwap`] type is a container for an `Arc` that can be changed atomically. Semantically,ÁüˆSP it is similar to something like `Atomic<Arc<T>>` (if there was such a thing) orÁüÜ\Y `RwLock<Arc<T>>` (but without the need for the locking). It is optimized for read-mostlyÁü¹;8 scenarios, with consistent performance characteristics.Áõú„ù
# MotivationÁŠúüŽ_\ There are many situations in which one might want to have some data structure that is oftenÁüîa^ read and seldom updated. Some examples might be a configuration of a service, routing tables,ÁüÐA> snapshot of some data that is renewed every few minutes, etc.Áúü–! In all these cases one needs:Áü¸c` * Being able to read the current value of the data structure, fast, often and concurrently fromÁœœ many threads.Áü°c` * Using the same version of the data structure over longer period of time ‒ a query should beÁü” b_ answered by a consistent version of data, a packet should be routed either by an old or by aÁü÷ EB new version of the routing table but not by a combination, etc.Áü½
:7 * Perform an update without disrupting the processing.Áø
úüü
c` The first idea would be to use [`RwLock<T>`][RwLock] and keep a read-lock for the whole time ofÁüà GD processing. Update would, however, pause all processing until done.Á¨ úü¬ c` Better option would be to have [`RwLock<Arc<T>>`][RwLock]. Then one would lock, clone the [Arc]Áü
a^ and unlock. This suffers from CPU-level contention (on the lock and on the reference count ofÁüò
`] the [Arc]) which makes it relatively slow. Depending on the implementation, an update may beÁüÓB? blocked for arbitrary long time by a steady inflow of readers.Áú ```rustÁü¦# # use std::sync::{Arc, RwLock};ÁüÊ  # use once_cell::sync::Lazy;Áüë]Z # struct RoutingTable; struct Packet; impl RoutingTable { fn route(&self, _: Packet) {} }ÁüÉJG static ROUTING_TABLE: Lazy<RwLock<Arc<RoutingTable>>> = Lazy::new(|| {Áü”+( RwLock::new(Arc::new(RoutingTable))Á });ÁÈúüÌ'$ fn process_packet(packet: Packet) {Áüô?< let table = Arc::clone(&ROUTING_TABLE.read().unwrap());Áä´ table.route(packet);Áü×+( # fn main() { process_packet(Packet); }Á ```Áúüa^ The [ArcSwap] can be used instead, which solves the above problems and has better performanceÁüñUR characteristics than the [RwLock], both in contended and non-contended scenarios.ÁÇú¯‹ä× # use arc_swap::ArcSwap;Áüô ñ‹ü•]›ŒüóFC static ROUTING_TABLE: Lazy<ArcSwap<RoutingTable>> = Lazy::new(|| {Áüº+( ArcSwap::from_pointee(RoutingTable)ÁŠŽîúüò'§Žüš)& let table = ROUTING_TABLE.load();ÁäÄ Åüç+Ô<“ˆú¤Ÿ # Crate contentsÁ´úü¸b_ At the heart of the crate there are [`ArcSwap`] and [`ArcSwapOption`] types, containers for anÁü›(% [`Arc`] and [`Option<Arc>`][Option].ÁÄúüÈb_ Technically, these are type aliases for partial instantiations of the [`ArcSwapAny`] type. TheÁü«c` [`ArcSwapAny`] is more flexible and allows tweaking of many things (can store other things thanÁü^[ [`Arc`]s, can configure the locking [`Strategy`]). For details about the tweaking, see theÁüîFC documentation of the [`strategy`] module and the [`RefCnt`] trait.Áµúü¹`] The [`cache`] module provides means for speeding up read access of the contained data at theÁüš  cost of delayed reclamation.Á»úü¿a^ The [`access`] module can be used to do projections into the contained data to separate partsÁü¡YV of application from each other (eg. giving a component access to only its own part ofÁüû=: configuration while still having it reloaded as a whole).Á¹ú”½ # Before usingÁÐúüÔEB The data structure is a bit niche. Before using, please check theÁüš MJ [limitations and common pitfalls][docs::limitations] and the [performanceÁüè KH characteristics][docs::performance], including choosing the right [readÁü´!2/ operation][docs::performance#read-operations].Áç!úüë!b_ You can also get an inspiration about what's possible in the [common patterns][docs::patterns]ÁdÎ" section.ÁÛ"úŒß" # Release 1.9Áñ"úüõ"^[ Unfortunately, several orderings were too weak in the original code (proofs based on wrongÁüÔ#_\ assumptions / wrong reading of the standard). The 1.9 version should fix them, but probablyÁü´$,) introduces some performance degradation.Áá$úüå$_\ I hope to re-design and rewrite from scratch eventually, with less amount of SeqCst needed.ÁÅ%útÉ% # ExamplesÁØ%ú\Ü%¯‹¼è% use std::sync::Arc;Á€&úÔ„& use arc_swap::ArcSwap;ÁüŸ&  use crossbeam_utils::thread;ÁÀ&úüÄ&<9 let config = ArcSwap::from(Arc::new(String::default()));ÁÜ' thread::scope
úüº
b_ For some cases, it is possible to use [`ArcSwapAny::map`]. If that is not flexible enough, theÁü )& [`Map`] type can be created directly.ÁÇ úüË _\ Note that the [`Access`] trait is also implemented for [`ArcSwapAny`] itself. Additionally,Áü« ^[ there's the [`Constant`] helper type, which is useful mostly for testing (it doesn't allowÁ
reloading).Áš
úŒž
 # PerformanceÁ°
úü´
_\ In general, these utilities use [`ArcSwapAny::load`] internally and then apply the providedÁü”2/ transformation. This has several consequences:ÁÇúüËa^ * Limitations of the [`load`][ArcSwapAny::load] apply ‒ including the recommendation to notÁü­VS hold the returned guard object for too long, but long enough to get consistency.Áü„YV * The transformation should be cheap ‒ optimally just borrowing into the structure.ÁÞú¾¤ñú¯‹¼î¤ü™(% use std::thread::{self, JoinHandle};Áä use std::time::Duration;ÁßúÔ㚥üþ2/ use arc_swap::access::{Access, Constant, Map};Á±úüµSP fn work_with_usize<A: Access<usize> + Send + 'static>(a: A) -> JoinHandle<()> {Áü‰ thread::spawn(move || {Áô© let mut value = 0;ÁüÈ while value != 42 {Áüè%" let guard = a.load();ÁüŽ value = *guard;Áü®&# println!("{}", value);ÁüÕ_\ // Not strictly necessary, but dropping the guard can free some resources, likeÁüµa^ // slots for tracking what values are still in use. We do it before the sleeping,Áü—/, // not at the end of the scope.ÁäÇ drop(guard);Áüä96 thread::sleep(Duration::from_millis(50));Á
 })ÁŽúüÁ'$ // Passing the whole thing directlyÁüéRO // (If we kept another Arc to it, we could change the value behind the scenes)Áü¼IF work_with_usize(Arc::new(ArcSwap::from_pointee(42))).join().unwrap();ÁúüŠ&# // Passing a subset of a structureÁ„±
struct Cfg {Á¬Â value: usize,ÁÅÞúüâ@= let cfg = Arc::new(ArcSwap::from_pointee(Cfg { value: 0 }));Áü£UR let thread = work_with_usize(Map::new(Arc::clone(&cfg), |cfg: &Cfg| &cfg.value));Áüù+( cfg.store(Arc::new(Cfg { value: 42 }));ÁÜ¥ thread.join().unwrap();ÁÁúüÅPM // Passing a constant that can't change. Useful mostly for testing purposes.Áü–2/ work_with_usize(Constant(42)).join().unwrap();Áˆ4æ,>?FMNß½¾Æôõ³o\ã³or,ÿé!Kœ†J”q¡Æ¦òH Š» 4ÀÇ
ä'Dݰ »+Tóû
° ,ÿÙÌÕÉ„ôªt‹ž xz´°iÌÌ\,ëOQ@BœòüˆC@ Abstracts over ways code can get access to a value of type `T`.ÁÌúüÐZW This is the trait that parts of code will use when accessing a subpart of the big dataÁü«FC structure. See the [module documentation](index.html) for details.Á¥ÎìüòÍìØD ƒ Ø)Ø/Íì˜ØØDô¤"é!ÜØŒ°"ÜØê!ØDT¶"ÔØ*îØ þØwyì¤"üŒ =: A guard object containing the value and keeping it alive.ÁÎ úüÖ [X For technical reasons, the library doesn't allow direct access into the stored value. AÁü¶!\Y temporary guard object must be loaded, that keeps the actual value alive for the time ofÁD—" use.Á,©"ôé#¼È" The loading method.Áä"úüì"_\ This returns the guard that holds the actual value. Should be called anew each time a freshÁ¤Ð# value is needed.Á$ì#Œ Œ˜ØÜØ ñ#
˜ØØD$ò#ü‹$D¥¡¾Dê!×JT³$Îì×J “$Íì¾D ª$×JÄDL$é!¾DŒ­$ÍìÄD $¾Dac^`TÖ$,Û$×JÄDìñ$$ô$ ¾D¾DÄD ù$
ÄD×J¾D$ú$ü¶%+8Ž¥Ž¤Ø »%ÐDTè%,í%>>?ÕAˆ âù&ØDì‡&$Š& ÐDÐDØD &
8ØD$&üÄ&28¥¤Ø É&ëD  Tý&,'·áìœ'$Ÿ' ëDëDØD ¤'
8ØD$¥'üÙ'98¥""¤Ø Þ'‰E#$$T™(,ž(!!·áì¸($»( ‰E‰EØD! À(!
$8ØD$Á(üõ(>¥&¤''&‹ß ú(ÍìòE …)ÇÄD4ý(°òEÄD\ˆ)¬E())EGBDTº),¿)%%õ]ìÙ)$Ü) ¬E¬EÄD% á)%
)ÄDòE$â)ü÷*=¥+¤,,+‹ß ü*ˆæ ÿ*°òEñF„‚+ÀF-.ê!ë!.0257\»+4À+**ÄD¬Ð+,Ó+ ÀF ÄD* Ù+*
.ÄDòE$Ú+ü,@¥0¤110‹ß •,ˆæ ˜,“è„›,õG233$&)+T×,,Ü,//ÀFì€-$ƒ- õGõGÄD/ ˆ-/
3ÄDòE$‰-üÊ-;¥5¤656‹ß Ï-ˆæ Ò-°òEùH|Õ-ÈH78ê!ë!80257\Œ.4.44ÄD¬¡.,¤. ÈH ÄD4 ª.4
8ÄDòE$«.üá.>¥:¤;:;‹ß æ.ˆæ é.äë|ì.ÎI<==$&)+T¦/,«/99ÈHìÎ/$Ñ/˜ ˜ÎIÎIÄD9 Ö/9
=ÄDòE$×/Q84ž0D²0¥@@ÎìÄD »0¡Jâù&?Až”q¡ˆˆ¢ˆl }.xÏé!ê!ÄDÀG¡JQ8¢âï¡J>>
?ÄD²´ÔÆ0>>âïüä0%¥CC·ï é0¡JDEê!ë!E\14•1BBÄD¬¥1,¨1 ¡J ÄDB ®1B
EÄD$¯1´ü6üÖ130 An object-safe version of the [`Access`] trait.ÁŠ2úüŽ2`] This can be used instead of the [`Access`] trait in case a type erasure is desired. This hasÁüï2`] the effect of performance hit (due to boxing of the result and due to dynamic dispatc
ª ªÀP’­ƒ ­
ƒ
8ØD
üç
# ¥‹ß ì
˜æ
ÛQüŽ + ¥‹ß ˜æ4– ÛQŠ{ŠüÀ « «ÛQ —Rˆ Ê ˆ
ŠÄD Ì„ ¥ŒŒ‹ß §R Ü¡ ¥ŽŽ‹ß ¦ §R{Ôà ¬ ¬§R§R Í 
ÄD Ü÷ ¥‹ß ü ¾R ì–
¥‹ß
¾R”{Ôº
­ ­¾R§R Ä

ÄD
lú,ü)& Caching handle into the [ArcSwapAny].ÁAúüEEB The [Cache] keeps a copy of the internal [Arc] for faster access.ÁúÌ [Arc]: std::sync::ArcÁ,-°½r,¹é!®¼À» 4÷ǘä'D”°»+T©ûš„®käÄ\´çL̃=Œ¢.œóü¶52 Generalization of caches providing access to `T`.Áìúüðb_ This abstracts over all kinds of caches that can provide a cheap access to values of type `T`.ÁüÓb_ This is useful in cases where some code doesn't care if the `T` is the whole structure or justÁŒ¶ a part of it.ÁÈúüÌ&# See the example at [`Cache::map`].Á¥œœØüóÀ¤Ø Ø"Ø(*,̘ü Loads the value from cache.Á±úü¹ZW This revalidates the value in the cache, then provides the access to the cached value.Á$® ®˜Ø ®ØD  
˜ØØDü×kŸ¥ ¤¡Ÿ ¡äLê!ûû»+þµ ÿå+Ÿ"ë§oŽB‹ØD¤Ì„¤Ø ßÍì÷½ âé!äLüþ Ø‘ Üð«°÷½ØDÖR¢£¤¥¦§46jlfhüÀ#üÉ! Creates a new caching handle.Áïúü÷^[ The parameter is something dereferencing into an [`ArcSwapAny`] (eg. either to [`ArcSwap`]ÁüÚ ]Z or [`ArcSwapOption`]). That can be [`ArcSwapAny`] itself, but that's not very useful. ButÁü¼!SP it also can be a reference to it or `Arc`, which makes it possible to share theÁü”"KH [`ArcSwapAny`] with multiple caches or access it in non-cached way too.Áä"úüì"+( [`ArcSwapOption`]: crate::ArcSwapOptionÁüœ# [`ArcSwap`]: crate::ArcSwapÁÇ#äLÖRžž
¢äLØD÷½DË#üÿ$$üº$@= Gives access to the (possibly shared) cached [`ArcSwapAny`].ÁD†%¯ ¯ÖR ¯äLê!ž %ž
£äLØD÷½$%äÕ(üÈ%# Loads the currently held value.Áð%úüø%RO This first checks if the cached value is up to date. This check is very cheap.ÁÏ&úü×&_\ If it is up to date, the cached value is simply returned without additional costs. If it isÁü»']Z outdated, a load is done on the underlying shared storage. The newly loaded value is thenÁü(%" stored in the cache and returned.Á$Ü(° °ÖR °ØDž á(ž
¤äLØD÷½$æ(üÊ)"”Í)± ±ÖR ±ØDž à)ž
¥äLØD÷½$á)Ä*T *² ²ÖR™jž «*ž
¦äLØD÷½$°*üˆ=Wü®.LI Turns this cache into a cache with a projection inside the cached value.Áÿ.úü‡/^[ You'd use this in case when some part of code needs access to fresh values of `U`, howeverÁüê/^[ a bigger structure containing `U` is provided by this cache. The possibility of giving theÁüÍ0\Y whole structure to the part of the code falls short in terms of reusability (the part ofÁü®1[X the code could be used within multiple contexts, each with a bigger different structureÁüŽ2WT containing `U`) and code separation (the code shouldn't needs to know about t
# WarningÁ˜3úü 3YV As the provided `f` is called inside every [`load`][Access::load], this one should beÁüþ3_\ cheap. Most often it is expected to be just a closure taking reference of some inner field.Áâ4úüê4\Y For the same reasons, it should not have side effects and should never panic (these willÁüË5QN not break Rust's safety rules, but might produce behaviour you don't expect).Á¡6út©6¾¤¼6ú\Ä6¯‹ÔÔ6š¥üó6)& use arc_swap::cache::{Access, Cache};Á¡7ú¬©7 struct InnerCfg {Á´Ã7 answer: usize,Á,Þ7Åè7ú¤ð7 struct FullCfg {Áĉ8 inner: InnerCfg,Á,¦8Ű8úü¸863 fn use_inner<A: Access<InnerCfg>>(cache: &mut A) {Áüó8! let value = cache.load();Áü™941 println!("The answer is: {}", value.answer);Á,Ò9ÅÜ9úüä92/ let full_cfg = ArcSwap::from_pointee(FullCfg {ÁÌ›: inner: InnerCfg {Á¼¹: answer: 42,ÁLÕ:ž«<ã:ŠŽüï:&# let cache = Cache::new(&full_cfg);Áüš;2/ use_inner(&mut cache.map(|full| &full.inner));ÁÑ;úüÙ;C@ let inner_cfg = ArcSwap::from_pointee(InnerCfg { answer: 24 });Áü¡<1. let mut inner_cache = Cache::new(&inner_cfg);Áü×<  use_inner(&mut inner_cache);Á<ü<ˆ=ÖRÜTœTž¨¦©¨©žÍìÜT “=ÍìâT =³“"ÜT ³ØD|Ï=³ÜT‹Ü˜" ³âTÜ=
§äLØD÷½ÜTâT$™=± Ÿ=|~üÀ>§«¥¬¤­«¬­ §½̃?ØDê!°Pä¬?‰¾ Ë>š¾üý> Ø‘ Å>é!ØDü¦?#¤Ø È>ð«4Ì?º¾\Û?ÖR®®:</1egüî? $ñ?´ ´ÖR ´ªSª ö?ª
®äLØD÷½$û?ü¶@w°¥±¤²±²°§½Ìï@¤Ø ¾@‰¾ Á@š¾üé@ Ø‘ »@ð«4’Aº¾\¡AÖR³ë³"$HJMOä´A$·AäLÖR¯¯
³äLØD÷½D¼Aü¿Dµ¥¤·¸¦¹¸¹·µ §½̆EµÜT µØD˜" µâTÙE‰¾ ÊDÜÛ ÍDìÛ ÐDš¾ü€E Ø‘ ÄDð«4©Eº¾\¸Eµ“"ÜTâ|ÌE¤Ø ÇDœTººBD!}ÄãE$æE œT âT´ ëE´
ºäLØD÷½ÜTâT$ðE´‰--D¡-$¥-ÃÐíçè AtomicUsizeÁ\—„ャœÀˆÁ» 4ƒÇ¼ÂÎË=Û ½À¼¾Ë¾À¼¾Ì=榿À¼¾ÌÀÀ¼¾G=í¬ÁÀ¼¾GÂÀ¼¾F5ç²ÃÀ¼¾FÄÀ¼¾×5Õ¶ÅÀ¼¾×ÆÀ¼¾üƒ;ä¨03"%$¼ÈÍÑÒa$áá.ÃÄIterÁ$øÄlÃÅ×:$¯çÃÇ×:èÃÇËq½ÀÃÆË¾ÀÃÆÌo¿ÀÃÆÌÀÀÃÆGmÁÀÃÆGÂÀÃÆFkÃÀÃÆFÄÀÃÆ×iÅÀÃÆ×~ÆÀÃÆ„Õ1Œëä‚ԶËeT ¤UÊüª I ¼·¸ ·¤U‹e ¸ïTÛ¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙ ·³YÉ Á É
Ê µ È ® üå#þÌÌÝUÍÎÏÈLÉLÊLÏêL$”ËË þ³YËËÄlÄl‹çÇlµ ™lÈl
end_or_lenÁ™lÉl_markerÁ™lŒœjSžþ³YüÏ$ÝUÝUÉLËË
Ïþ\–¼ÙÚÛÜÝ×ÛÜa$ò4á.Ðѵ ‚5ÐÒ¶yLÅ5¯]ÐÕûã\Ð5„ÄÐÖ×:$ê5çÐ××:èÐ×» 4û5ÇÐØÎË*½ÀÐÓË?¾ÀÐÓÌ(¿ÀÐÓÌ=ÀÀÐÓG&ÁÀÐÓG:ÂÀÐÓF$ÃÀÐÓF8ÄÀÐÓ×"ÅÀÐÓ×7ÆÀÐÓ„æ4rLü4dä‹5”°5Z]JM\ã5>lô5ü„6 |Ž6eÄ­6<·6eÌÎ6DØ6‹e¬ð6$ú6‹e¼É9,Û9¼ÝVâyU=øžÞßàáâ¤ô@<ô@ÐÝÝ™vT®A$®AÐÝݳYıB\±BÐÝÝ™v”ŒEDŒEÐÝÝ£VüëF \ëFÐÝݤ]¤]V¦]Á‚]üß3ø¤”& £V´GÝVä´ä¤­G<°GÝVãã
äTóKÝVæçèëìü„L"$L¼¹ ¹ÝV ¹³Yå —Lå
æ$˜LüÇLIDÕL¼º» ºÝV‹e »îU‹eå ÞLå
ç$ßLµ åL®,ñLüúV„$ˆW¼¼½¾ ¼ÝV ½ÝV‹e ¾£™jå£é¥êéê “WåÍìé÷ W¤Ø Wð«4áW"é÷™jLôWé÷™j˜"ØD üW
èé÷ØD$”WwhoÁšW storage_addrÁd¦W replacementÁ\»Wƒˆì„~$’~¼¿ ¿ÝV™jå —~å
ë$œ~üé~I<÷~¼À ÀÝV‹e‹eÖ¿Ù¿Ú¿«Û¿ˆÜ¿Ý¿Þ¿ˆ‚†f|Â
™j‹eå ÿ~å
ì$€5µ ¼þÿƒˆœàa$Å
á.íîµ Õ
íï‹ç
Älíð¶yL¯ ¯]íóûã „Äíô”q¦ íõ FastLocalÁLÇ Íí÷ FastSlotsÁLÛ Ñíø HelpingLocalÁd…
×íú HelpingSlotsÁdœ
Ýíû×:$¶
çíü×:èíü» 4Ç
ÇíýÎËa ½ÀíñËv ¾ÀíñÌ_ ¿ÀíñÌt ÀÀíñG] ÁÀíñGq ÂÀíñF[ ÃÀíñFo ÄÀíñ×Y ÅÀíñ×n ÆÀíñ„¹

ŒÞ
äõ
”š øûè뜖 Ü  Å ®  ˜,“
~
p
MÄÐ

íe´î

í‹eÔŠlí‹eüÑ!í¤]¤]V¦]Á‚]üß3ø¤”& €XÃÞ:þƒýˆí AWÍÀ£¾k~þAWÍÀ£¾k~ƒ þ€X´‚Þ:ƒí‡ƒ´‚
ƒþ²í‡ƒüÂ!8ÁÁÂW‡"”ê ÂÂW™j ò
8´ø€X¬f{ÞgÚŠŒ|•$•툈¤U¬ªíˆˆÝVœÅ툈™vŒ‚$‚툈 €XÜ™t™íˆˆ™v¬¹€X´¤Õ€XŽŽ
€X‘šüÜVêKÛ¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙé÷£¥ø óÍ ö“"êK €Xüù!êK舘"Ö‡L
é÷êK±  NPSUÄ® íà ÀX™j À 
ÄÇ#tÊ#íÄ Ä€X™j Ù#
$Ú#üû*3t+ŠŀXƒýˆí AWÍÀ£¾k~Å ‘+
$’+Ìž-¡-íêˆ
4‘.<closure_kind>Á˜<closure_signature>Á˜<upvars>Á˜˜˜ÅwÛ¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙÅw™j¢2ËÜ‹ú‹™jÅw™jü†;1T”;Æ Æ€XÄlÄl‹çÇlµ ™lÈlÃì™lÉlÙì™lŒœjSžÆ³Y Ÿ;
š$ ;ü„<*d<Ç Ç€X dzY Ÿ<
$ <ܤ=L¶=æXc7û‘„<[žŸ¯ü×>!$×>휜á.á.aã.»Ì-IÜžB2®Û¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙêˆ|­?$­?휜ïT¬÷?<÷?휜îUt‘@æX¡¦§¨«üÝ@<»ºü°@%ü¯@'ü¦@2$ë@êKé÷ £¢££¢ ¥ø ð@Í ó@È"êK ÈæX¼ö@ÈêK…”˜"é÷ ŒA
¡é÷êK± A^`ce4êA¡Ë¤Ü‹¤ú‹¤¤¡¤é÷êK æXé÷ á.á.aã.»Ì-IÜžB2®Û¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙêK÷F¡Ë¥Ü‹¥ú‹¥¥¡¥é÷êKåHåHæH AccessErrorÁ –úrì$šÙ0é÷Õ•üÃOBDÑOÉ ÉæX‹eÛ¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙ ³Y  ÚO 
¦$ÛOµ áOü³R5\ÁRÊ ÊæX‹e‹e  ÍR 
§$ÎRµ ÔRüØXŒ|æXË ËæX‹e‹eÖ¿Ù¿Ú¿«Û¿ˆÜ¿Ý¿Þ¿ˆ‚†f|Â
â˜â˜‹e  ÿX 
¨$€Y5ŽYµ ¢Y$å[¨Ë©Ü‹©ú‹©©¨©™j ³Y Šœ4…\¨ËªÜ‹ªú‹ªª¨ª‹eŠœ‹e“œüø]„$†^¼ÌÍÎ ÌæX Í€X‹e Îé÷™j £¬¥­¬­ ‘^ ¥ø ‹^¤Ø Ž^ð«4ß^ÆøLò^Ùø ú^
«é÷ØD$’^‚ø˜^ød¤^¡ø\¹^RTWY¼à`æX¯"¯”þ`$aÏ ÏæX™j® †a®
¯$‹a³Y±ä  °°‹e¬¸ 
 Additional documentation.Á
úü"_
\ Here we have some more general topics that might be good to know that just don't fit to theÁ´‚
 crate level intro.Á
úü_
\ Also, there were some previous blog posts about the crate which you might find interesting.Áý
ú´
 # Atomic orderingsÁ˜
úüœa
^ Each operation on the [`ArcSwapAny`] with [`DefaultStrategy`] type callable concurrently (eg.Áüþc
` [`load`], but not [`into_inner`]) contains at least one [`SeqCst`] atomic read-write operation,Áüâ_
\ therefore even operations on different instances have a defined global order of operations.ÁÂ
ú
# FeaturesÁÕ
úüÙV
S The `weak` feature adds the ability to use arc-swap with the [`Weak`] pointer too,Áü°c
` through the [`ArcSwapWeak`] type. The needed std support is stabilized in rust version 1.45 (asÁ¤”
 of now in beta).Á©
úü­_
\ The `experimental-strategies` enables few more strategies that can be used. Note that theseÁüc
` **are not** part of the API stability guarantees and they may be changed, renamed or removed atÁ
any time.Áÿ
úüƒb
_ The `experimental-thread-local` feature can be used to build arc-swap for `no_std` targets, byÁüæ]
Z replacing occurences of [`std::thread_local!`] with the `#[thread_local]` directive. This矀 H
E requires a nightly Rust compiler as it makes use of the experimentalÁü
a
^ [`thread_local`](https://doc.rust-lang.org/unstable-book/language-features/thread-local.html)Áüï
a
^ feature. Using this features, thread-local variables are compiled using LLVM built-ins, which矄 %
" have [several underlying modes ofÁü÷ c
` operation](https://doc.rust-lang.org/beta/unstable-book/compiler-flags/tls-model.html). To addÁüÛ a
^ support for thread-local variables on a platform that does not have OS or linker support, theÁü½
a
^ easiest way is to use `-Ztls-model=emulated` and to implement `__emutls_get_address` by hand,Á
as in [thisÁü¯
| example](https://opensource.apple.com/source/clang/clang-800.0.38/src/projects/compiler-rt/lib/builtins/emutls.c.auto.html)Á
from Clang.Á¿
úôÃ
 # Minimal compiler versionÁâ
úüæ^
[ The `1` versions will compile on all compilers supporting the 2018 edition. Note that this矁^
[ applies only if no additional feature flags are enabled and does not apply to compiling orÁ”¤
 running tests.Á·
úü»%
" [`ArcSwapAny`]: crate::ArcSwapAnyÁüá'
$ [`ArcSwapWeak`]: crate::ArcSwapWeakÁü‰%
" [`load`]: crate::ArcSwapAny::loadÁü¯1
. [`into_inner`]: crate::ArcSwapAny::into_innerÁüá/
, [`DefaultStrategy`]: crate::DefaultStrategyÁü‘3
0 [`SeqCst`]: std::sync::atomic::Ordering::SeqCst瓁
 [`Weak`]: std::sync::WeakÁ$³-½¾¿À„ä
¬  Internal details.Á úüb _ While the other parts of documentation are useful to users of the crate, this part is probablyÁü}` ] helpful only if you want to look into the code or are curious about how it works internally.ÁÞ úüâ] Z Also note that any of these details may change in future versions and are not part of theÁüÀ6 3 stability guarantees. Don't rely on anything here.Á÷ úÔû  # Storing the [`Arc`].Á úüš_ \ The [`Arc`] can be turned into a raw pointer and back. This is abstracted by the [`RefCnt`]ÁüúZ W trait and it is technically possible to implement it for custom types (this crate alsoÁüÕY V implements it for [`Rc`] and [`Weak`], though the actual usefulness of these is a bitÁ”¯  questionable).Á úüÆ6 3 The raw pointer is stored inside an [`AtomicPtr`].Áý úü$ ! # Protection of reference countsÁ¦ úüªb _ The first idea would be to just use [`AtomicPtr`] with whatever the [`Arc::into_raw`] returns.Áü] Z Then replacing it would be fine (there's no need to update ref counts). The load needs toÁüëc ` increment the reference count ‒ one still stays inside and another is returned to the caller.ÁüÏ^ [ This is done by re-creating the Arc from the raw pointer and then cloning it, throwing oneÁü® * ' instance away (without destroying it).ÁÙ úüÝ c ` This approach has a problem. There's a short time between we read the raw pointer and incrementÁüÁ
c ` the count. If some other thread replaces the stored Arc and throws it away, the ref count couldÁü¥ a ^ drop to 0, get destroyed and we would be trying to bump ref counts in a ghost, which would beÁœ‡  totally broken.Á úüŸ G D To prevent this, we actually use two approaches in a hybrid manner.Áç úüë [ X The first one is based on hazard pointers idea, but slightly modified. There's a globalÁüÇ
a ^ repository of pointers that owe a reference. When someone swaps a pointer, it walks this listÁü©B ? and pays all the debts (and takes them out of the repository).Áì úüð` ] For simplicity and performance, storing into the repository is fallible. If storing into theÁüÑ^ [ repository fails (because the thread used up all its own slots, or because the pointer gotÁü°\ Y replaced in just the wrong moment and it can't confirm the reservation), unlike the fullÁüT Q hazard-pointers approach, we don't retry, but fall back onto secondary strategy.Áâ úüæb _ The secondary strategy is similar, but a bit more complex (and therefore slower, that's why itÁüÉb _ is only a fallback). We first publish an intent to read a pointer (and where we are reading itÁü¬H E from). Then we actually do so and publish the debt, like previously.Áõ úüùc ` The writer pays the debts as usual. But also, if it sees the intent to read the value, it helpsÁüÝ^ [ along, reads it, bumps the reference and passes it to the reader. Therefore, if the readerÁü¼Y V fails to do the protection itself, because it got interrupted by a writer, it finds aÁü–\ Y ready-made replacement value it can just use and doesn't have to retry. Also, the writerÁüób _ doesn't have to wait for the reader in any way, because it can just solve its problem and moveÁ  on.ÁÞ ú # UnsafetyÁñ úüõa ^ All the uses of the unsafe keyword is just to turn the raw pointer back to Arc. It originatedÁü×d a from an Arc in the first place, so the only thing to ensure is it is still valid. That means itsÁü¼!  ref count never dropped to 0.ÁÞ úüâ] Z At the beginning, there's ref count of 1 stored in the raw pointer (and maybe some othersÁüÀ` ] elsewhere, but we can't rely on these). This 1 stays there for the whole time the pointer isÁü¡` ] stored there. When the arc is replaced, this 1 is returned to the caller, so we just have toÁü‚5 2 make sure no more readers access it by that time.Á¸ ú´¼  # Leases and debtsÁÓ úü×d a Instead of incrementing the reference count, the pointer reference can be owed. In such case, itÁü¼` ] is recorded into a global storage. As each thread has its own storage (the global storage isÁüc ` composed of multiple thread storages), the readers don't contend. When the pointer is no longerÁü  in use, the debt is erased.Á¡ úü¥d a The writer pays all the existing debts, therefore the reader have the full Arc with ref count atÁüŠ ] Z that time. The reader is made aware the debt was paid and decrements the reference count.Áè úœì  # Memory ordersÁ€! úü„!8 5 ## Synchronizing the data pointed to by the pointer.Á½! úüÁ!d a We have AcqRel (well, SeqCst, but that's included) on the swap and Acquire on the loads. In caseÁü¦"^ [ of the double read around the debt allocation, we do that on the *second*, because of ABA.Áü…#O L That's also why that SeqCst on the allocation of debt itself is not enough.ÁüÕ#c ` the *latest* decrement. By making both the increment and decrement AcqRel, we effectively chainÁ¼¹$  the edges together.ÁÑ$ úüÕ$  # Memory orders around debtsÁö$ úüú$[ X The linked list of debt nodes only grows. The shape of the list (existence of nodes) isÁüÖ%U R synchronized through Release on creation and Acquire on load on the head pointer.Á¬& ú
Ϛ
ü$ ! Limitations and common pitfalls.Á% úŒ)  # Sized typesÁ; úü?g d This currently works only for `Sized` types. Unsized types have „fat pointers“, which are twiceÁü§` ] as large as the normal ones. The [`AtomicPtr`] doesn't support them. One could use somethingÁüˆ` ] like `AtomicU128` for them. The catch is this doesn't exist and the difference would make itÁüéL I really hard to implement the debt storage/stripped down hazard pointers.Á úüº. + A workaround is to use double indirection:Áé ú ¯‹äù ‡’Ì–  // This doesn't work:Áü°D A // let data: ArcSwap<[u8]> = ArcSwap::new(Arc::from([1, 2, 3]));Áõ ú¬ù  // But this does:ÁüN K let data: ArcSwap<Box<[u8]>> = ArcSwap::from_pointee(Box::new([1, 2, 3]));ÁŒÞ  # drop(data);Á ˆø úüü] Z It also may be possible to use `ArcSwap` with the [`triomphe::ThinArc`] (that crate needsÁüÚ9 6 enabling a feature flag to cooperate with `ArcSwap`).Á ú̘  # Too many [`Guard`]sÁ² úü¶^ [ There's only limited number of "fast" slots for borrowing from [`ArcSwap`] for each singleÁü•c ` thread (currently 8, but this might change in future versions). If these run out, the algorithmÁôù  falls back to slower path.Á˜ úüœ a ^ If too many [`Guard`]s are kept around, the performance might be poor. These are not intendedÁüþ F C to be stored in data structures or used across async yield points.ÁÅ
úüÉ
 ‘ÂÜé
 [`Guard`]: crate::GuardÁü… / ßðµ úü¹   # No `Clone` implementationÁÙ úüÝ c ` Previous version implemented [`Clone`], but it turned out to be very confusing to people, sinceÁüÁ ] Z it created fully independent [`ArcSwap`]. Users expected the instances to be tied to eachÁüŸ
Q N other, that store in one would change the result of future load of the other.Áñ
úüõ
F C To emulate the original behaviour, one can do something like this:Á¼ ú ¯‹äÌ ‡’üé* ' # let old = ArcSwap::from_pointee(42);Áü”, ) let new = ArcSwap::new(old.load_full());Á”Á  # let _ = new;Á ˆÜ úüàW T [`triomphe::ThinArc`]: https://docs.rs/triomphe/latest/triomphe/struct.ThinArc.htmlÁ
„‹
¼
 Common use patternsÁ
úüc
` Here are some common patterns one can use for inspiration. These are mostly covered by examplesÁü€J
G at the right type in the crate, but this lists them at a single place.ÁË
úüÏ#
# Sharing of configuration dataÁó
úü÷^
[ We want to share configuration from some source with rare updates to some high performanceÁüÖR
O worker threads. It can be configuration in its true sense, or a routing table.Á©
úü­a
^ The idea here is, each new version is a newly allocated in its own [`Arc`]. It is then storedÁü'
$ into a *shared* `ArcSwap` instance.Á·
úü»_
\ Each worker then loads the current version before each work chunk. In case a new version isÁü›_
\ stored, the worker keeps using the loaded one until it ends the work chunk and, if it's theÁüûX
U last one to have the version, deallocates it automatically by dropping the [`Guard`]ÁÔ
úüØ^
[ Note that the configuration needs to be passed through a *single shared* [`ArcSwap`]. ThatÁü·`
] means we need to share that instance and we do so through an [`Arc`] (one could use a globalÁ´˜
 variable instead).Á¯
úü³6
3 Therefore, what we have is `Arc<ArcSwap<Config>>`.Áê
ú
¯‹Ìú
 # use std::sync::Arc;Áü” 4
1 # use std::sync::atomic::{AtomicBool, Ordering};Á´É
 # use std::thread;Áôà
 # use std::time::Duration;Á,ÿ
ä…
‡’”¢
 # struct Work;Áüµ
P
M # impl Work { fn fetch() -> Self { Work } fn perform(&self, _: &Config) {} }Á,†
ùìŒ
 #[derive(Debug, Default)]Áœª
 struct Config {Áü¾
 // ... Stuff in here ...Á
Åå
úüé K
H // We wrap the ArcSwap into an Arc, so we can share it between threads.Áüµ D
A let config = Arc::new(ArcSwap::from_pointee(Config::default()));Áú
úüþ 5
2 let terminate = Arc::new(AtomicBool::new(false));Áü´
!
 let mut threads = Vec::new();ÁÖ
úüÚ

 // The configuration threadÁüú
 threads.push(thread::spawn({Áü›)
& let config = Arc::clone(&config);矁/
, let terminate = Arc::clone(&terminate);ÁŒõ
 move || {Áü‡6
3 while !terminate.load(Ordering::Relaxed) {Áü¾6
3 thread::sleep(Duration::from_secs(6));Áüõ3
0 // Actually, load it from somewhereÁü©=
: let new_config = Arc::new(Config::default());Áüç)
& config.store(new_config);Ál
èË
ž«
À†²
úĶ
 // The worker threadÁ¤Ï
 for _ in 0..10 {Áüä$
! threads.push(thread::spawn({Áü‰-
* let config = Arc::clone(&config);Áü·3
0 let terminate = Arc::clone(&terminate);Á¬ë
 move || {Áü:
7 while !terminate.load(Ordering::Relaxed) {Áü¼-
* let work = Work::fetch();Áüê/
, let config = config.load();Áüš*
' work.perform(&config);ÁŒÅ
ìªl×
èË
}));Á
Åø
úÜü
 // Terminate gracefullyÁü˜-
* terminate.store(true, Ordering::Relaxed);ÁÜÆ
 for thread in threads {Áüâ
 thread.join().unwrap();Á,
Å<ˆ
ˆ
úÔ”
 # Consistent snapshotsÁ¯
úü³Z
W While one probably wants to get a fresh instance every time a work chunk is available,ÁüŽb
_ therefore there would be one [`load`] for each work chunk, it is often also important that theÁüñ[
X configuration doesn't change in the *middle* of processing of one chunk. Therefore, oneÁüÍc
` commonly wants *exactly* one [`load`] for the work chunk, not *at least* one. If the processingÁü±;
8 had multiple phases, one would use something like this:Áí
ú
¯‹Ìý
ÓŽ,—
ùä
‡’¤º
 # struct Config;Á”Ï
Ή
 # impl Work {Áüô%
" # fn fetch() -> Self { Work }Áüš*
' # fn phase_1(&self, _: &Config) {}矁*
' # fn phase_2(&self, _: &Config) {}Á
 # }Áüø;
8 # let config = Arc::new(ArcSwap::from_pointee(Config));Áì´
 let work = Work::fetch();ÁüÒ
 let config = config.load();ÁÔò
 work.phase_1(&config);Áü)
& // We keep the same config value hereÁÔ·
 work.phase_2(&config);Á
ˆÚ
ú
Over this:Áí
ú
¯‹Ìý
ÓŽ,—
ùä
‡’¤º
Õ£”Ï
Ή
ÿ£üô%
š¤üš*
ɤüÅ*
ý¤
°¥üø;
Á¥ì´
…¦üÒ !
 work.phase_1(&config.load());Áüô _
\ // WARNING!! This is broken, because in between phase_1 and phase_2, the other thread couldÁüÔ!a
^ // have replaced the config. Then each phase would be performed with a different one and thatÁü¶"
 // could lead to surprises.ÁüÖ"!
 work.phase_2(&config.load());Á<ø"
ˆ€#
úü„#"
 # Caching of the configurationÁ§#
úü«#b
_ Let's say that the work chunks are really small, but there's *a lot* of them to work on. MaybeÁüŽ$`
] we are routing packets and the configuration is the routing table that can sometimes change,Á¼ï$
 but mostly doesn't.Á‡%
úü‹%c
` There's an overhead to [`load`]. If the work chunks are small enough, that could be measurable.Áüï%[
X We can reach for [`Cache`]. It makes loads much faster (in the order of accessing localÁüË&
œ
ü  Performance characteristics.Á!úü%LI There are several performance advantages of [`ArcSwap`] over [`RwLock`].ÁrúÄv ## Lock-free readersÁúü“WT All the read operations are always [lock-free]. Most of the time, they are actuallyÁüë\Y [wait-free]. They may wait from time to time, with at least `usize::MAX / 4` [wait-free]ÁôÈ accesses in between waits.Áçúäë Writers are [lock-free].ÁˆúüŒ_\ Whenever the documentation talks about *contention* in the context of [`ArcSwap`], it talksÁüìeb about contention on the CPU level ‒ multiple cores having to deal with accessing the same cacheÁüÒ\Y line. This slows things down (compared to each one accessing its own cache line), but anÁü¯b_ eventual progress is still guaranteed and the cost is significantly lower than parking threadsÁü’# as with mutex-style contention.Áú
## SpeedsÁÈúüÌZW The base line speed of read operations is similar to using an *uncontended* [`Mutex`].Áü§ZW However, [`load`] suffers no contention from any other read operations and only slightÁü‚VS ones during updates. The [`load_full`] operation is additionally contended only onÁüÙYV the reference count of the [`Arc`] inside ‒ so, in general, while [`Mutex`] rapidlyÁü³ RO loses its performance when being in active use by multiple threads at once andÁü†
`] [`RwLock`] is slow to start with, [`ArcSwap`] mostly keeps its performance even when read byÁìç
 many threads in parallel.Á úü‰ a^ Write operations are considered expensive. A write operation is more expensive than access toÁüë UR an *uncontended* [`Mutex`] and on some architectures even slower than uncontendedÁüÁ C@ [`RwLock`]. However, it is faster than either under contention.Á
úü‰
b_ There are some (very unscientific) [benchmarks] within the source code of the library, and theÁüì
YV [`DefaultStrategy`][crate::DefaultStrategy] has some numbers measured on my computer.ÁÆúüÊb_ The exact numbers are highly dependent on the machine used (both absolute numbers and relativeÁü­c` between different data structures). Not only architectures have a huge impact (eg. x86 vs ARM),Áü‘`] but even AMD vs. Intel or two different Intel processors. Therefore, if what matters is moreÁüòXU the speed than the wait-free guarantees, you're advised to do your own measurements.ÁËúüÏIF Further speed improvements may be gained by the use of the [`Cache`].Áú ## ConsistencyÁ°úü´]Z The combination of [wait-free] guarantees of readers and no contention between concurrentÁü’a^ [`load`]s provides *consistent* performance characteristics of the synchronization mechanism.Áüô`] This might be important for soft-realtime applications (the CPU-level contention caused by aÁüÕ]Z recent update/write operation might be problematic for some hard-realtime cases, though).Á³úü·+( ## Choosing the right reading operationÁãúüçVS There are several load operations available. While the general go-to one should beÁü¾MJ [`load`], there may be situations in which the others are a better match.ÁŒúüZW The [`load`] usually only borrows the instance from the shared [`ArcSwap`]. This makesÁüë\Y it faster, because different threads don't contend on the reference count. There are twoÁüÈYV situations when this borrow isn't possible. If the content gets changed, all existingÁü¢VS [`Guard`]s are promoted to contain an owned instance. The promotion is done by theÁüùa^ writer, but the readers still need to decrement the reference counts of the old instance whenÁüÛ30 they no longer use it, contending on the count.Áúü“c` The other situation derives from internal implementation. The number of borrows each thread canÁü÷]Z have at each time (across all [`Guard`]s) is limited. If this limit is exceeded, an ownedÁüÕ  instance is created instead.Áöúüúa^ Therefore, if you intend to hold onto the loaded value for extended time span, you may preferÁüÜVS [`load_full`]. It loads the pointer instance ([`Arc`]) without borrowing, which isÁü³b_ slower (because of the possible contention on the reference count), but doesn't consume one ofÁü–[X the borrow slots, which will make it more likely for following [`load`]s to have a slotÁüò`] available. Similarly, if some API needs an owned `Arc`, [`load_full`] is more convenient andÁüÓ LI potentially faster then first [`load`]ing and then cloning that [`Arc`].Á !úü¤![X Additionally, it is possible to use a [`Cache`] to get further speed improvement at theÁü€"\Y cost of less comfortable API and possibly keeping the older values alive for longer thanÁtÝ" necessary.Áì"úüð"‘Âü#"òÙܳ#èýüÏ#%кüõ#/, [`load_full`]: crate::ArcSwapAny::load_fullÁÜ¥$ÔïüÁ$ [`Mutex`]: std::sync::MutexÁüá$! [`RwLock`]: std::sync::RwLockÁüƒ%HE [benchmarks]: https://github.com/vorner/arc-swap/tree/master/benchesÁüÌ%RO [lock-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm#Lock-freedomÁüŸ&RO [wait-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedomÁ
\¹-<½-Çí
ëÁµ IÁÃKd†JÁÅÆiòHÁÆŠäY:„¾ÁìLlLC]tSOQ;=ô¤üo85 A trait describing smart reference counted pointers.Á¨úü¬a^ Note that in a way [`Option<Arc<T>>`][Option] is also a smart reference counted pointer, justÁÜŽ one that can hold NULL.Áªúü®SP The trait is unsafe, because a wrong implementation will break the [ArcSwapAny]Áü‚" implementation and lead to UB.Á¥úü©`] This is not actually expected for downstream crate to implement, this is just means to reuseÁüŠb_ code for [Arc] and [`Option<Arc>`][Option] variants. However, it is theoretically possible (ifÁüí,) you have your own [Arc] implementation).ÁšúüžXU It is also implemented for [Rc], but that is not considered very useful (because theÁü÷^[ [ArcSwapAny] is not `Send` or `Sync`, therefore there's very little advantage for it to beÁ atomic).Áãú # SafetyÁôúüø`] Aside from the obvious properties (like that incrementing and decrementing a reference countÁüÙb_ cancel each out and that having less references tracked than how many things actually point toÁü¼_\ the value is fine as long as the count doesn't drop to 0), it also must satisfy that if twoÁüœ b_ pointers have the same value, they point to the same object. This is specifically not true forÁüÿ b_ ZSTs, but it is true for `Arc`s of ZSTs, because they have the reference counts just after theÁüâ
`] value. It would be fine to point to a type-erased version of the same object, though (if oneÁüà @= could use this trait with unsized types in the first place).Á úüˆ 41 Methods in this trait must not panic nor unwind.Á½ úüÁ \Y Furthermore, the type should be Pin (eg. if the type is cloned or moved, it should stillÁüž
-* point/deref to the same place in memory).ÁÌ
úÌÐ
Ñ´¬ê
 [Rc]: std::rc::RcÁü€# [ArcSwapAny]: crate::ArcSwapAnyÁÇÇØü¤©Ø˜ØÇØ*‘™Ø6‘™ÉÊËÌÍÈÉÊËÌÍÍì˜ØÈâ™ÍËÉÌÊüÉ(% The base type the pointer points to.Á$ûÇÇü‡)ü†YV Converts the smart pointer into a raw pointer, without affecting the reference count.Áäúüì\Y This can be seen as kind of freezing the pointer ‒ it'll be later converted back usingÁüÍ# [`from_ptr`](#method.from_ptr).Áõúüý^[ The pointer must point to the value stored (and the value must be the same as one returnedÁüà" by [`as_ptr`](#method.as_ptr).ÁDŠ˜Ø ê™ÇÇ
ɘØmeÁüÒ(ü¶<9 Provides a view into the smart pointer as a raw pointer.Á÷úüÿNK This must not affect the reference count ‒ the pointer is only borrowed.Á4ÕÑ Ñ˜Ø§žÇ àÇ
ʘØÈÜü‚3ü€^[ Converts a raw pointer back into the smart pointer, without affecting the reference count.ÁãúüëXU This is only called on values previously returned by [`into_ptr`](#method.into_ptr).ÁüÈa^ However, it is not guaranteed to be 1:1 relation ‒ `from_ptr` may be called more times thanÁü®\Y `into_ptr` temporarily provided the reference count never drops under 1 during that timeÁüXU (the implementation sometimes owes a reference). These extra pointers will either beÁüì1. converted back using `into_ptr` or forgotten.Á¢ú°»úüÃ:7 This must not be called by code outside of this crate.ÁDŒ ꙘØÇÇ
˘ص ü²$ü»*' Increments the reference count by one.Áêúüò;8 Return the pointer to the inner thing as a side effect.ÁµÒ ҘاžÇ ½Ç
̘ØÈ¹üû%üŒ*' Decrements the reference count by one.Á»úüÃDA Note this is called on a raw pointer (one previously returned byÁüŒ]Z [`into_ptr`](#method.into_ptr). This may lead to dropping of the reference count to 0 andÁüî(% destruction of the internal pointer.Áú°´úü¼:Ϥ£¦™jÇÇ
͘ص üÏ ¥ÏÏ‹ß ÛñFÐÑÒÓÈÉÊËÒÑÓ/1ÎÎÄDü‰!ñF§RÎÎ
ÑÄDÈüÛ Ó ÓñF§RÎ éÎ
ÒÄDÈåüÈ)+DÒ)¾RñFÎÎ
ÓÄDµ Û)üš*¥ÕÕ‹ß ¦*ùHÖרÙÈÉÊËÙØ×/1LÀ*$Å*ÔÔÄDüÓ* DÖ*ùH§RÔÔ
×ÄDÈß*ü£+4¦+Ô ÔùH§RÔ ±+Ô
ØÄDÈ­+ü5*D—5¾RùHÔÔ
ÙÄDµ  5üÝ5+¥ÛÛ‹ß é5˜æ4ì5‰ZÜÝÞßÈÉÊËÞÝß79L6$”6ÚÚ—Rü¨6*D«6‰Zð°ÚÚ
ÝÄDÈ´6ü™7)4œ7Õ Õ‰Zð°Ú §7Ú
ÞÄDÈ£7ü84Dš8¼¡‰ZÚÚ
ßÄDµ £8„ë-ü30 Strategies for protecting the reference counts.Á4úü8a^ There are multiple algorithms how t
strategy.Áðúüôb_ For now, the traits in here are sealed and don't expose any methods to the users of the crate.Áü×\Y This is because we are not confident about the details just yet. In the future it may beÁü´]Z possible for downstream users to implement their own, but for now it is only so users canÁü’ choose one of the provided.Á²úü¶a^ It is expected that future strategies would come with different capabilities and limitations.Áü˜b_ In particular, some that are not "tight" in the cleanup (delay the cleanup) or not support theÁüû  compare and swap operations.Áœúü (% Currently, we have these strategies:ÁÉúüÍ74 * [`DefaultStrategy`] (this one is used implicitly)Áü…'$ * [`RwLock<()>`][std::sync::RwLock]Á­ú
# TestingÁ¿úüÃb_ Formally, the [`RwLock<()>`][std::sync::RwLock] may be used as a strategy too. It doesn't haveÁü¦ a^ the performance characteristics or lock-free guarantees of the others, but it is much simplerÁüˆ
c` and contains less `unsafe` code (actually, less code altogether). Therefore, it can be used forÁüì
(% testing purposes and cross-checking.Á úü™ [X Note that generally, using [`RwLock<Arc<T>>`][std::sync::RwLock] is likely to be betterÁüõ [X performance wise. So if the goal is to not use third-party unsafe code, only the one inÁüÑ `] [`std`], that is the better option. This is provided mostly for investigation and testing ofÁü²
@= [`ArcSwap`] itself or algorithms written to use [`ArcSwap`].Áó
úü÷
63 *This is not meant to be used in production code*.Á®úü²‘ÂüÒ%кDó-䞟 °µY4‹ àá¶yL«¯]àâ» 4ËÇàãÜ;lùàœÜ;úàœ<tžÿà¤ýì—p´»a¬ÔõùúÿY4« äåíëäç ManuallyDropÁdÉÃÛäèr,çé!äéµ øäê¶yL•¯]äëÁ'Ú¬äîŒ'lß§äï¤%Lî£äð×:$Œçäò×:èäò¬L’œäóÀ» 4²Çäô˽Àäì˾ÀäìÌ¿ÀäìÌÀÀäìGÁÀäìGÂÀäìFÃÀäìFÄÀäì×ÅÀäìׯÀäì¤úì½ÒÕ„Üǹì«ä¤¡¤ƒx{TW´¢Eü»&„Æ¥öö‹ß טæÑ[¹Òóû÷O¡÷ø*,Üèäõõ˜¤‰ äõõÃÛÃÛËÅÅÛ»¬µÜÀ,%*ÄDü¢ #¥úú‹ß § ˜æÑ[ûüýþüÌ Rá ༡˜Ñ[ùù
ûÄDµ å üÈ J äÖ× ÖæX פ]¤]V¦]Á‚]üß3ø¤”&ð°Û¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙÑ[ù Ù ù
üÄD½ storageÁ<å üÕCäØÙ ØæX ÙÎÑ[ù çù
ýÄD½¼Îüß""4â"äÚ ÚÑ[¼¡ù é"ù
þÄD$ê"ü±#,¥‹ß ¶#˜æ4¹#Ñ["”ò#$õ#Û ÛÑ[™jÿ ú#ÿ
ÄD$ÿ#ü‡*4¥ƒƒ‹ß Œ*˜æ4*Ñ[„¦¥%'ìÐ*TÓ*ÄDÑ[
ÄDµ Þ*äã+Tæ+Ñ[ÄD
ÄD$õ+üò11¥‹ß ÷1˜æ4ú1Ñ[ˆ¢ˆ´¸24»2Ü ÜÑ[ ÜÄD Â2
ˆÄD$Ã2„ì24ö2Øüì2eØØŠŠ¤º3DÀ3ìˆ4¢QŒŠ¤¬4D²4ü§5[¥Ž™%Ž‹ß ¬5Íì¾]¯5˜æ4ê5¾]4û5‘]©ª«KMHJt‰6LŽ6Ñ[ü³6F$½6ÝÞ Ý‘] ÞΑ]ÄD© Â6
ÄD¾]$Ã6¼Î<É64”7ËÜ‹ú‹ÄD¾]ÕÑ[  ÎÙ8ËÜ‹ú‹ÄD¾]™jÑ[®¦êÙüœ9T„¦9ßà ß‘]¼¡ àΙj ·9
ÄD¾]$¸9oldÁ¾9¼Î<Ó9Ï<ËÜ‹ú‹ÄD¾]‡j™jÄD  ‘]êÙüË=;¥™%˜˜‹ß Ð=…×Û=˜æ4Ó=×4à=‘]™®*,/1ü„—>áâ á‘] âÎÄDÂØšš Ó>Íì•Þ ¨>y•Þ—Rì«>
ÄD¾]•Þ$Ô>¼Î<â>currentÁ<ˆ?æ œ?LNd€ð ó Ì Ï Ä¨%̰ The default strategy.ÁÊúüÎB? It is used by the type aliases [`ArcSwap`][crate::ArcSwap] andÁü‘b
# ExampleÁ=ú\‰=¯‹ü™=63 # use arc_swap::{ArcSwap, DefaultStrategy, Guard};ÁÌÔ=ÓŽüò=(% # let p = ArcSwap::from_pointee(42);ÁüŸ>41 // Create two guards pointing to the same objectÁ´Ø> let g1 = p.load();Áüó>GD let g2 = Guard::<_, DefaultStrategy>::from_inner(Arc::clone(&*g1));Á|¿? # drop(g2);Á<Ó?ˆTæ?ÄDõ]ÝÝ
áÄDòEÓ),ñ?üÜ@5¥ã¤ääã‹ß á@ˆæ ì@˜æ4ä@§æ\ï@õ]åæê!ë!æ1368\˜A4AââÄD¬»A,¾Aé éõ] éÄDâ ÄAâ
æÄDòE$ÅAüøA7¥è¤éèé‹ß ýAˆæ ˆB˜æ4€B§æ\‹Bõ]êëê*,/1̶B$¹BÄDõ]çç
êÄDòEÓ),¾BüûBA¥ì¤íìí‹ß €Cˆæ •C³ÄD<ƒC˜æ4C§æ\˜Cõ]î´î9;>@¤ÃC<ÆCõ]ëë
îÄDòEü„D=¥ð¤ñðñ‹ß ‰Dˆæ œD¿cÄD,ŒD˜æ4”D§æ\ŸDõ]òÀcò9;>@üÈD5ËDêëì êõ] ë c cˆ¢cµ
 `£cbufÁ `àB¤GS
ìÖ¿Ù¿Ú¿«Û¿ˆÜ¿Ý¿Þ¿ˆ‚†f|Â
™jŸÈŸÈ ÈErrorÁ O˜éBLï ÏDï
òÄDòE$ÐD formatterÁLÖDü­EA¥ô¤õôõ‹ß ²Eˆæ ÇEÄcÄD<µE˜æ4¿E§æ\ÊEõ]öÅcö9;>@üõE5øEíîï íõ] î c cˆ¢cµ
 `£cÒ¦ `àB¤GS
ïù§ó üEó
öÄDòE$ýE ¨LƒFü­HW4°H×JÉ øùúøúùÍìÉ $·H±û ½HÍ씬 ÀHy×JÛ¬\äHy”¬Û¬\øH
÷Û¬×J”¬¬ ÃH­ ÉHbdgiceü¹[BüÌIZW An atomic storage for a reference counted smart pointer like [`Arc`] or `Option<Arc>`.Á§Júü«J`] This is a storage where a smart pointer may live. It can be read and written atomically fromÁüŒK;8 several threads, but doesn't act like a pointer itself.ÁÈKúüÌKLI One can be created [`from`] an [`Arc`]. To get the pointer back, use theÁÜ™L [`load`](#method.load).ÁµLúT¹L # NoteÁÄLúüÈL\Y This is the common generic implementation. This allows sharing the same code for storingÁü¥MDA both `Arc` and `Option<Arc>` (and possibly other similar types).ÁêMúüîMHE In your code, you most probably want to interact with it through theÁü·Nc` [`ArcSwap`](type.ArcSwap.html) and [`ArcSwapOption`](type.ArcSwapOption.html) aliases. However,Áü›O`] the methods they share are described here and are applicable to both of them. That's why theÁüüO]Z examples here use `ArcSwap` ‒ but they could as well be written with `ArcSwapOption` orÁŒÚP `ArcSwapAny`.ÁìPú¬ðP # Type parametersÁ†QúüŠQc` * `T`: The smart pointer to be kept inside. This crate provides implementation for `Arc<_>` andÁüîQ`] `Option<Arc<_>>` (`Rc` too, but that one is not practically useful). But third party couldÁüÏRIF provide implementations of the [`RefCnt`] trait and plug in others.Áü™SYV * `S`: Chooses the [strategy] used to protect the data inside. They come with variousÁüóS`] performance trade offs, the default [`DefaultStrategy`] is good rule of thumb for most useÁdÔT cases.ÁáTútåT¾¤ôTú\øT¯‹Ì„UÓŽäžU‡’Ü»U let arc = Arc::new(42);Áü×U&# let arc_swap = ArcSwap::from(arc);ÁüþU&# assert_eq!(42, **arc_swap.load());Áü¥V$! // It can be read multiple timesÁüÊV&–»ñVúìõV // Put a new one in thereÁô“W let new_arc = Arc::new(0);Áü²W,) assert_eq!(42, *arc_swap.swap(new_arc));ÁüßW%" assert_eq!(0, **arc_swap.load());Á<…XˆXú„‘X
# Known bugsÁ¢Xúü¦X`] Currently, things like `ArcSwapAny<Option<Option<Arc<_>>>>` (notice the double Option) don'tÁü‡Y96 work properly. A proper solution is being looked intoÁüÁY74 ([#81](https://github.com/vorner/arc-swap/issues)).ÁùYúüýY?< [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.htmlÁü½ZYV [`from`]: https://doc.rust-lang.org/nightly/std/convert/trait.From.html#tymethod.fromÁü—[! [`RefCnt`]: trait.RefCnt.htmlÁTÄ[¥ü¤ýüý‹ß Ï[ˆæüÚ[ ˜æ4Ò[§æ\Ý[¬Eë§oŽB‹þÿˆ=?B Ú[õP¼Ú\Ú\ûûÎäæ]dæ]ûû³oFu\»ŸÄD\¯^D¯^ûûòEü¿^F¥¤ƒƒ‹ß Ä^ˆæ Ï^˜æ4Ç^³òE<Ò^§æ\Ü^¬E„ë9;>@¼Œ_$_ÄD¬E
ÄDòE¹”_üÞ_9¥¤‹ß ã_ˆæ î_˜æ4æ_§æ\ñ_¬Eˆ"ˆ*,/1”ž`$¡`ð ð¬E™j ¦`
ˆÄDòE$«`üºbO¥Š¤Š‹ß ¿bˆæ Âb§æ\Åb¨¦,úb˜æ4‚c¬EŒÀcŒ2479üc5“cñòó ñ¬E ò c cˆ¢cµ
 `£cÒ¦ `àB¤GS
óù§ —c
ŒÄDòE$˜c ¨LžcüÁdS¥Ž¤Ž‹ß Ædˆæ Éd§æ\Ìdí©<ƒe˜æ4e¬EÅc2479ü›e5žeôõö ô¬E õ c cˆ¢cµ
 `£cÒ¦ `àB¤GS
öù§ ¢e
ÄDòE$£e ¨L©eüÿeP¥¤‹ß „fˆæ ™f˜æ4‡fæ¤<fÅ<œf§æ\¦f¬E”´:<?A¤Öf<Ùf¬E
ÄDòEü–g0¥¤‹ß ›gˆæ ¦g˜æ4žg§æ\©g¬E˜šœžŸ¡¤=?BDüïg8ìÍg Constructs a new storage.ÁögÄD¬EÅ<Ÿh
˜ÄDòE¹úgüi1üÑhGD Constructs a new storage while customizing the protection strategy.Ál¤iÄDòE¬E
ÄDòE¹²iŸ"Dºiü‡m ôäl Extracts the value inside.ÁTŽm¬EÄD
šÄDòE$mäÁq¤þn Loads the value.Á—oúüŸoQN This makes another copy of the held pointer and returns it, atomically (it isÁüõoPM safe even when other thread stores into the same instance at the same time).ÁÊpúüÒpJG The method is lock-free and wait-free, but usually more expensive thanÁÜ¡qú¯LÈq÷ ÷¬EÄD Òq
ÄDòE$Óqüâ‚!ü’r52 Provides a temporary borrow of the object inside.ÁÌrúüÔrZW This returns a proxy object allowing access to the thing held inside. However, there'sÁü³s^[ only limited amount of possible cheap proxies in existence for each thread ‒ if more areÁü–tXU created, it falls back to equivalent of [`load_full`](#method.load_full) internally.Áótúüût]Z This is therefore a good choice to use for eg. searching a data structure or juggling theÁüÝu]Z pointers around a bit, but not as something to store in larger amounts. The rule of thumbÁü¿v[X is this is suited for local variables on stack, but not in long-living data structures.ÁŸwúŒ§w # ConsistencyÁ½wúüÅw[X In case multiple related operations are to be done on the loaded value, it is generallyÁü¥x\Y recommended to call `load` just once and keep the result over calling it multiple times.Áü†y_\ First, keeping it is usually faster. But more importantly, the value can change between theÁüêyZW calls to load, returning different objects, which could lead to logical inconsistency.ÁüÉz:7 Keeping the result makes sure the same object is used.Áˆ{ú\{¯‹ä {‡’”Á{ struct Point {ÁŒØ{ x: usize,ÁŒî{ y: usize,Á,„|ÅŽ|úü–|)& fn print_broken(p: &ArcSwap<Point>) {ÁüÄ|NK // This is broken, because the x and y may come from different points,Áü—}>; // combining into an invalid point that never existed.ÁüÚ}&# println!("X: {}", p.load().x);Áü…~JG // If someone changes the content now, between these two loads, weÁÌÔ~ // have a problemÁüò~&# println!("Y: {}", p.load().y);Á,ŧúü¯*' fn print_correct(p: &ArcSwap<Point>) {ÁüÞMJ // Here we take a snapshot of one specific point so both x and y comeÁì°€ // from the same one.ÁìÒ€ let point = p.load();Áüô€# println!("X: {}", point.x);Áüœ# println!("Y: {}", point.y);ÁÅüÎ<9 # let p = ArcSwap::from_pointee(Point { x: 10, y: 20 });ÁÄ # print_correct(&p);Á¼¬‚ # print_broken(&p);Á<È‚ˆ$邸 ø¬Eõ] î‚
œÄDòE$ï‚܇…üöƒ,) Replaces the value inside this instance.Á§„úü¯„SP Further loads will yield the new value. Uses [`swap`](#method.swap) internally.Á,Ž…ù ù¬EÄD™j ”…
ÄDòE$•…¹›…ü€†üÎ…-* Exchanges the value inside this instance.Á$‡†ú ú¬EÄDÄD Œ†
žÄDòE$æ “†ü¦|üÁ‰30 Swaps the stored A
tÝå êå ìå ùô òå Žæ , óå8Ð $ôå& øå8¼,úå$ ÿå, æ8Ÿ"D‚æ& Šæ8´Œæ*æ “æ öô+ æ žæ ¨æ8âŸæ ¢æ §æ8$£æ8²æ, ¶æ8Ð $·æ ¼æ ðôà8#Êæ8¤,Îæ'Óæ8Ó$4Õæ'Ûæ8ToOwnedÁ<Ýæ% äæ8#òæ8¤,öæ'ûæ8stringÁ4ýæ'ƒç8ß4…ç% ‹ç8#™ç8¤,ç'¢ç8Á¤ç'§ç8ö©ç% ¬ç8#ºç8í$¾ç'Âç8ç$Äç'Èç8atomicÁ4Êç'Ðç Òç äç8$Óç$ ×ç8ûã\Ùç% åç8#ôç8adaptive_barrierÁ„øç'ˆè Šè è8BarrierÁ<‹è$ ’è8 PanicModeÁL”è% žè8#¬è8crossbeam_utilsÁ|°è'¿è8Š4Áè% Çè8#Öè8,Úè'ßè
áè% âè8,ñè8
ITERATIONSÁT÷è& é8¬,ƒé ‰é710Á‹é% é+ œé é ¯é8«,žé £é ®é8±T¤é8!$ðé8AsÁõé ÷é8¥ øé ùé ûé8»+Týé ‡ê8Kˆê ‹ê8¥ Œê ê$ Žê, ê8Ÿ"D‘ê ™ê% šê+ ¨ê ©ê »ê8«,ªê ¯ê ºê8±T°ê8!$üê8AsoÁë „ë8¥ …ë †ë ˆë8»+TŠë ”ë8¬4•ë ›ë8Kœë Ÿë8¥  ë¡ë$ £ë, ¥ë8Ÿ"D¦ë ®ë% ¯ë<R Similar to the one in doc tests of the lib, but more times and more intensive (weÁü¾ëU< want to torture it a bit).Áô ì+ Ëì Ìì Ñì8$Íì+ ßì àì ÷ì8äDáì éì öì8µ $êì$ îì8Á4ðì8 ·í8publishÁ<ºí Áí Âí Äí ó÷8,Öí8READERSÁ<Üí& ãí8¬,åí ëí7Š íí% îí8
€î8 „î8†î7ˆ ‰î!Šî8ÏTŒî —î å÷08­î8configÁ4±î ¸î8¡Ðºî'¼î ¾î8ß4¿î Åî'Æî8><Èî Ïî Ðî% Ñî8çî8endedÁ,ëî ñî8ûã\óî'þî8æ €ï ƒï …ï7ˆ „ï% †ï8Š4œï'¢ï8scopeÁ,¤ï ©ï Äõ ªï8ˆÙ,«ï °ï ²ï Ãõ 8
Ìï8 Ðï8Òï7ˆ Õï!Öï8õÕ<Øï àï Þó8ˆÙ,þï ƒð8spawnÁ,„ð ‰ð Ãó Šð8 ‹ð Œð8$Žð “ð Âó8µð8â¹ð ½ð8–×4¿ð Åð8Å-LÆð Ïð Ðð% Ñð8óð öð8â÷ð úð8is_emptyÁDûð ƒñ „ñ †ñ êò 8ÔL¬ñ µñ ¶ñ Ðñ
·ñ8â¸ñ$ »ñ7New configurationÁœ½ñ% Ññ8–Ø,÷ñ üñ8 fetch_addÁLýñ †ò ›ò7 ‡ò$ ˆò8®DŠò'’ò8Ë<”ò% œò84Âò% Èò8ÍÌ4Œó'’ó8spin_loop_hintÁt”ó ¢ó £ó% ¤ó% Äó8ˆÙ,øó ýó8»Ú,þó ƒô ¬õ „ô8 …ô †ô ˆô «õ
8¦ô8new_confÁDªô ³ô8Kµô'¸ô8æ ºô ½ô Üô7€Ýœ¾ô Ñô8to_ownedÁDÒô Úô Ûô% Ýô8–×4ûô õ8È,‚õ ‡õ õ8âßDˆõ% ‘õ% ­õ Úõ8¢4Ûõ áõ âõ% ãõ8ÔLùõ ‚ö ƒö ªö8õÕ<„ö$ ‹ö8–Ø,ö ’ö8¬$“ö —ö ©ö8®D˜ö' ö8Ë<¢ö% «ö8Áö8arcÁÅö Éö8–×4Ëö Ñö8Å-LÒö Ûö Üö% Ýö8ÔLóö üö ýö ˜÷7Š þö$ ÿö8K÷'„÷8 strong_countÁd†÷ ’÷ —÷ “÷8€ã”÷% ™÷8ÔL¯÷ ¸÷ ¹÷ Ò÷7ˆ º÷$ »÷8K½÷'À÷8
weak_countÁTÂ÷ Ì÷ Ñ÷ Í÷8€ãÎ÷% Ó÷<= Similar to the doc tests of ArcSwap, but happens more times.Áü‚ø@+ Ïø Ðø Õø8$Ñø8 ãø8 swap_loadÁLæø ïø ðø òø Ø€8
„ù8 ˆù8Šù7ˆ ù!Žù7100Áù ”ù Ê€@8ªù8€ã®ù ²ù8K´ù'·ù8æ ¹ù ¼ù ¿ù742Á½ù% Àù8Öù8DÚù ãù8¡Ðåù'çù8÷$éù íù þù8Kîù'ñù8ƒ,óù øù ýù ùù8€ãúù% ÿù8ÔL•ú žú Ÿú µú7»è ú$ ¢ú
¤ú
¥ú8D¦ú ®ú8¬$¯ú ³ú ´ú% ¶ú8ÔLû Šû ‹û ¡û7»èŒû$ Žû
û
‘û8D’û šû8¬$›û Ÿû  û% ¢û8çû8new_arcÁ<ëû óû8Kõû'øû8æ úû ýû ÿû7ˆ þû% €ü8ÔL–ü Ÿü  ü Éü7»è¡ü$ £ü
¥ü8D¦ü ®ü8æ-$¯ü ³ü Èü8K´ü'·ü8ƒ,¹ü ¾ü Çü ¿ü8öë<Àü% Êü8ÔLàü éü êü ÿü7ˆ ëü$ ìü
îü
ïü8Dðü øü8¬$ùü ýü þü% €ý8âý8loadedÁ4æý íý8Dïý ÷ý8Å-Løý þ ‚þ% ƒþ8ÔL™þ ¢þ £þ Áþ7 ¤þ$ ¥þ8K§þ'ªþ8šäd¬þ ¸þ Àþ ¹þ8™ï4ºþ% Âþ8ÔLØþ áþ âþ þþ7ˆ ãþ$ äþ8Kæþ'éþ8©åTëþ õþ ýþ öþ8™ï4÷þ% ÿþ8ÔLØÿ áÿ âÿ ýÿ7 ãÿ$ äÿ8Kæÿ'éÿ8šädëÿ ÷ÿ üÿ øÿ8€ãùÿ% þÿ8ÔL”€  ž€ ·€7ˆ Ÿ€$  €8K¢€'¥€8©åT§€ ±€ ¶€ ²€8€ã³€% ¸€<Q Two different writers publish two series of values. The readers check that it isÁüç€T<" always increasing in each series.ÁüÈ%<úú<3 For performance, we try to reuse the threads here.ÁüŠ‚6+ Í‚ ΂ Ó‚8$Ï‚8 á‚8
multi_writersÁlä‚ ñ‚ ò‚ ô‚ G8†ƒ8 first_valueÁ\Šƒ –ƒ8K˜ƒ'›ƒ8æ ƒ  ƒ §ƒ ¡ƒ ¦ƒ7ˆ ¢ƒ$ £ƒ7ˆ ¥ƒ% ¨ƒ8ºƒ8sharedÁ4¾ƒ Ń8¡Ðǃ'Ƀ8÷$˃ σ èƒ8KЃ'Óƒ8ƒ,Õƒ Úƒ çƒ Ûƒ8Çö\܃% éƒ8,ûƒ8
WRITER_CNTÁT& ‹„8¬, “„7Š •„% –„8,¨„8
READER_CNTÁT®„& ¸„8¬,º„ À„7 „% Ä+ Õ„ Ö„ à„8âׄ Ú„ ß„8µ $Û„8,ò„8ÏTø„& ‚…8¬,„… Š…7 Œ…% + Ÿ…  … ¯…8â¡… ¤… ®…8
¥… ¨… ­…8µ $©…8,Á…8ÏTÇ…& Ñ…8¬,Ó… Ù…7ÎçÛ…% Þ…8,ð…8SEQÁö…& ù…8¬,û… 750Áƒ†% …†8—†8barrierÁ<›† £†8ÜÍ<¥†'¬†8æ ®† ±† Æ8÷ÍL²†'»†8PoisonÁ4½†% Ć8Š4Ö†'܆8ˆÙ,Þ† ㆠؘ ä†8ˆÙ,å† ê† ì† ט8
‚‡8 †‡8ˆ‡7ˆ ‹‡!Œ‡8øøTއ ™‡ ¼8½ˆ8Áˆ8“ý<ň ͈8“ý<ψ Öˆ8ƒ,׈ ܈ ݈% Þˆ8øˆ8Ø÷4üˆ ƒ‰ …‰8Ø÷4†‰% Œ‰8¦‰8Çö\ª‰ ¶‰ ¸‰8Çö\¹‰% ĉ8ˆÙ,Þ‰ ã‰8»Ú,ä‰ é‰ ¥8$ê‰ ï‰8 ð‰ ñ‰ ó‰ ¤8
‘Š8 •Š8—Š7ˆ šŠ!›Š8ÏTŠ ¨Š Š8“ý<ÊŠ ÑŠ8waitÁ$ÒŠ ÖŠ ׊% ØŠ8Ø÷4úŠ €‹8È, †‹ Ÿ‹8K‡‹'Š‹8ƒ,Œ‹ ‘‹ ž‹ ’‹8Çö\“‹%  ‹8“ý<‹ É‹8æ‚$Ê‹ ΋ Ï‹% Ћ8
ò‹8´ ö‹8ø‹7ˆ û‹!ü‹8Æüþ‹ ‚Œ ìŒ8Ø÷4¨Œ ®Œ8È,¯Œ ´Œ ÉŒ8KµŒ'¸Œ8æ ºŒ ½Œ ÈŒ ¾Œ ÇŒ8 ¿Œ$ ÀŒ8´ ÂŒ ÄŒ7 ÆŒ% ÊŒ% ¦8
Ò8 Ö8Ø7ˆ Û!Ü8Êù é ¡˜8ƒŽ8‡Ž8“ý<‹Ž “Ž8“ý<•Ž œŽ8ƒ,Ž ¢Ž £Ž% ¤Ž8¾Ž8Ø÷4ÂŽ ÉŽ ËŽ8Ø÷4ÌŽ% ÒŽ8ìŽ8Çö\ðŽ üŽ þŽ8Çö\ÿŽ% Š8ˆÙ ©8»Ú ¯ Š˜8 µ8  · ¹ ‰˜8
×8 Û8Ý7ˆ à!á8Ï î ï—8“ý< 8æ‚ œ % ž8“ý Ç8æ‚ Ì Í% Î8ð8ô8previousÁ  ƒ‘ ‘‘7ˆ „‘% …‘8øøT‡‘% ’‘8´‘8¸‘8$¼‘ Á‘8KÑ'Æ‘8ƒ,È‘ Í‘ Ú‘ Α8Çö\Ï‘% Û‘8$ý‘ ‚’ Ñ—*8¨’8curÁ¬’ °’8Ø÷4²’ ¸’8¬$¹’ ½’ ¾’% ¿’8å’8Kè’'ë’8–+4í’ ó’ ÿ’ ô’8$õ’$ ù’ û’8¤ü’  ›”8ÍÌ4«“'±“8ÃÞt³“ Á“ “% Ó8Dí“% õ“8Á” Å” Ê”8 Ɣ$ Ç”8¾ É” Ì”
Δ
Ï”8¤Д% Ó”8Ó4ù” ÿ” €• ¯•
8µ‹D ‰• ‹•8Â Š• 8¾ $ 7 {:?} vs {:?}Át’•$  •8µ‹D¢•$ ª•8¤¬•% °•8µ‹DÖ• Þ• à•8 ߕ â•8¾ ä•% å•8$‹– 8° ,’–'—–8´$T™– £– §–8¤¤–% ¨–8Ζ8¾ Ñ–Ó–8ÆüÖ– Ú– ¯—8,„—% ‰—% ‹˜8ã$¸˜ ¼˜ Ę8“ý<½˜% Ř ê˜8¢4ë˜ ñ˜ ò˜% ó˜+  ‘™ –™8$’™8 ¤™8 load_nullÁL§™ °™ ±™ ³™ Á›!8Å™8Ø÷4É™ Й8ƒÒÒ™'Õ™ ×™8¬,Ø™ Ý™'Þ™8><à™ ç™ è™% é™8û™8£,ÿ™ …š8Ø÷4‡š š8¬$Žš ’š “š% ”š8Ó4¦š ¬š ­š ½š8£,®š ³š8is_noneÁ<´š »š ¼š% ¾š8Ø÷4К Öš8È,ך Üš ïš8Û$Ýš áš îš8Kâš'åš8æ çš êš íš7»èëš% ðš8ÔL‚› ‹› Œ› ²›7»è$ 
‘›
’›8Ø÷4“› ™›8¬$š› ž› Ÿ›  ›8É4¡› §› ¨› ©›8¢4ª› °› ±›% ³›+ Л Ñ› Ö›8$Ò›8 ä›8 from_intoÁLç› ð› ñ› ó› Õž/8…œ8¬ ‰œ ‹œ8Kœ'œ8æ ’œ •œ ˜œ7»è–œ% ™œ8«œ8Ø÷4¯œ ¶œ8¡Ð¸œ'ºœ8æ ¼œ ¿œ Áœ8¬ Àœ% œ8Ôœ8£,Øœ Þœ8Ø÷4àœ æœ8¬$çœ ëœ ìœ% íœ8ÿœ8¬ ƒ 8Ø÷4‡ 8´$ ˜ % š8Ô µ  ½7»è·$ ¹
»8¬ ¼% ¾8Ô Ù Ú ó7Š Û$ Ü8KÞ'á8šä ï ò ð8¬ ñ% ô8ã$†ž Šž ž8£,‹ž% ‘ž8ÔL£ž ¬ž ­ž Æž7 ®ž$ ¯ž8K±ž'´ž8šäd¶ž ž Åž Þ8¬ Äž% Çž+ ¹¡ º¡ Ê¡8º4»¡ Á¡ É¡8q<¡84Ø¡8
ReportDropÁTß¡ é¡ ú¡8Kê¡ í¡8ûã\î¡ ù¡% û¡8$‰¢8DropÁ$Ž¢8
“¢8°¡T—¢ ¢¢ ££8 ´¢8ã$·¢ »¢ Å¢ ¼¢8½¢8$Á¢ Ç¢ •£8$Ý¢ á¢7ˆ ⢠ã¢8ºÝLä¢ í¢ ‚£7 î¢$ ï¢8®Dñ¢'ù¢8Ë<û¢% ƒ£<: Interaction of two threads about a guard and dropping it.Áü²£=<úü£<X We make sure everything works in timely manner (eg. dropping of stuff) even if multipleÁüŒ¤[< threads interact.Á¬ô¤<ú–¥<
The idea is:Á„¦¥< * Thread 1 loads a value.ÁìÃ¥<K * Thread 2 replaces the shared value. The original value is not destroyed.Áüí¥N<[ * Thread 1 drops the guard. The value is destroyed and this is observable in both threads.ÁüȦ^+ ³§ ´§ ¹§8$µ§8 ǧ8guard_drop_in_threadÁ¤Ê§ Þ§ ß§ á§ ĸ8
ó§8 ÷§8ù§7ˆ ü§!ý§8ÏTÿ§ Ѝ ¶¸$8 ¨8cntÁ¤¨ ¨¨8Kª¨'­¨8æ ¯¨ ²¨ ƨ8ûã\³¨'¾¨8æ À¨ è Ũ7ˆ Ĩ% Ǩ8Þ¨8Ø÷4⨠é¨8¡Ðë¨'í¨8ç.dï¨ û¨ “©8°¡Tü¨ †© ’©8Ω‡© Š©8ƒ,‹© © ‘©% ”©8ÔLª© ³© ´© ê©8Ωµ© ¸©8¬$¹© ½© Ï©8®D¾©'Æ©8Ë<È©$ Щ7ˆ Ò©$ Ó©7Dropped prematurelyÁ¬Õ©% ë©8Ϊ8ç$Òª ת8ÜÍ<Ùª'àª8æ âª åª ÷ª8÷ÍLæª'ïª8óý4ñª% øª8Š4«'•«8ˆÙ,—« œ« …¸ «8ˆÙ,ž« £« ¥« „¸
8ˆÙ,¿« Ä«8»Ú,Å« Ê« §± Ë« ¦± 8é«8ç$í« ò«8ç$ô« ø«8ƒ,ù« þ« ÿ«% €¬ ž¬8 Ÿ¬  ¬ ¢¬ Œ±$8Ĭ8Ȭ8ç$̬ Ѭ8ç$Ó¬% ׬8’­8£,–­ œ­8Ø÷4ž­ ¤­8¬$¥­ ©­ ª­% «­8ç$Í­ Ñ­8æ‚$Ò­ Ö­ ×­% Ø­8ç$Ü® à®8æ‚$á® å® æ®% ç®8ã$‰¯ ¯ “¯8£,ޝ% ”¯8ÔL¶¯ ¿¯ À¯ ô¯8ΩÁ¯ į8¬$ů ɯ Û¯8®Dʯ'Ò¯8Ë<Ô¯$ ܯ7 Þ¯$ ߯7Value not droppedÁœá¯% õ¯8ç$ã° ç°8æ‚$è° ì° í°% î°% ¨±8ˆÙ,ñ ȱ8»Ú,ɱ α í· ϱ8 б ѱ Ó± ì·"8ñ±8õ±8ç$ù± þ±8ç$€²% „²8ç$â² æ²8æ‚$ç² ë² ì²% í²8Ø÷4‹³ ‘³8È,’³ —³ ª³8q<˜³'Ÿ³8><¡³ ¨³ ©³% «³8ÔLɳ Ò³ Ó³ ޵8Ωõ³ ø³8¬$ù³ ý³ ´8®Dþ³'†´8Ë<ˆ´$ ´7ˆ ²´$ ³´7Dropped while still in useÁäÕ´% µ8ç$íµ ñµ8æ‚$òµ öµ ÷µ% øµ8ç$ê¶ î¶8æ‚$ï¶ ó¶ ô¶% õ¶8ÔL“· œ· · Ñ·8Ωž· ¡·8¬$¢· ¦· ¸·8®D§·'¯·8Ë<±·$ ¹·7 »·$ ¼·7Ž´œ¾·% Ò·% î· ›¸8¢4œ¸ ¢¸ £¸% ¤¸<S Check dropping a lease in a different thread than it was created doesn't cause anyÁüÓ¸V<
problems.Ál¶¹+ й ѹ Ö¹8$Ò¹8 ä¹8guard_drop_in_another_threadÁäç¹ ƒº „º †º ú¿8
˜º8 œº8žº7ˆ ¡º!¢º8ÏT¤º ¯º ì¿/8ź8Ωɺ ͺ8KϺ'Òº8æ Ôº ׺ ëº8ûã\غ'ãº8æ åº èº êº7ˆ éº% ìº8‚»8Ø÷4†» »8¡Ð»'‘»8ç.d“» Ÿ» ·»8°¡T » ª» ¶»8Ω«» ®»8ƒ,¯» ´» µ»% ¸»8ÔLλ ×» Ø» ޼8ΩÙ» Ü»8¬$Ý» á» ó»8®Dâ»'ê»8Ë<ì»$ ô»7ˆ ö»$ ÷»7­¬ù»% ¼8¥¼8£,©¼ ¯¼8Ø÷4±¼ ·¼8¬$¸¼ ¼¼ ½¼% ¾¼8ã$Õ¼ Ù¼ à¼8Ø÷4Ú¼% á¼8ÔL÷¼ €½ ½ ·½8Ω‚½ …½8¬$†½ н œ½8®D‹½'“½8Ë<•½$ ½7ˆ Ÿ½$  ½7­¬¢½% ¸½8Š4Ͻ'Õ½8ˆÙ,×½ ܽ ë¾ ݽ8ˆÙ,Þ½ ã½ å½ ê¾8ˆÙ,ÿ½ „¾8»Ú,…¾ о Ó¾ ‹¾8 Œ¾ ¾ ¾ Ò¾8ã$­¾ ±¾ ·¾8£,²¾% ¸¾% Ô¾ ¿8¢4‚¿ ˆ¿ ‰¿% Š¿8ÔL¡¿ ª¿ «¿ Ù¿8Ω¬¿ ¯¿8¬$°¿ ´¿ Æ¿8®Dµ¿'½¿8Ë<¿¿$ Ç¿7 É¿$ Ê¿7 Not droppedÁlÌ¿% Ú¿+ ‰À ŠÀ À8$‹À8 À8 load_optionÁ\ À «À ¬À ®À ¤Ã"8ÀÀ8Ø÷4ÄÀ ËÀ8ƒÒÍÀ'ÐÀ8ç.dÒÀ ÞÀ áÀ7»èßÀ% âÀ8ÛÁ8optÁßÁ& âÁ8¬4äÁ êÁ8 ëÁ ìÁ îÁ8° ,ðÁ'õÁ8´$T÷Á  Â8Ø÷4‚ ˆÂ8¬$‰Â  ŽÂ% Â8ÔL¢Â «Â ¬Â ¾Â7»è­Â$ ¯Â
±Â8–ɲ µÂ8¢4¶Â ¼Â ½Â% ¿Â8Ø÷4Ò ØÂ8È,Ù Þ ãÂ8©$ßÂ% äÂ8Ó4ö ü ý •Ã8Ø÷4þ „Ã8¬$…à ‰Ã ŠÃ ‹Ã8ˆ—<ŒÃ “à ”Ã% –Ã+ àà áà æÃ8$âÃ8 ôÃ8
debug_implÁT÷Ã Ä ‚Ä „Ä ÐÅ8–Ä8Ø÷4šÄ ¡Ä8¡Ð£Ä'¥Ä8ç.d§Ä ³Ä ¶Ä7»è´Ä% ·Ä8ÔLÉÄ ÒÄ ÓÄ þÄ7ArcSwapAny(42)Á„ÔÄ$ äÄ æÄ8formatÁ4çÄ íÄ îÄ ýÄ7{:?}Á4ïÄ$ õÄ8Ø÷4÷Ä% ÿÄ8ÔL‘Å šÅ ›Å ÁÅ7»è$œÅ$  Å ¢Å8•Ï4£Å ©Å ªÅ ÀÅ7¿Ï4«Å$ ±Å8Ø÷4³Å ¹Å8¬$ºÅ ¾Å ¿Å% ÂÅ+ ßÅ àÅ åÅ8$áÅ8 óÅ8 display_implÁdöÅ ‚Æ ƒÆ …Æ ÁÇ8—Æ8Ø÷4›Æ ¢Æ8¡Ð¤Æ'¦Æ8ç.d¨Æ ´Æ ·Æ7»èµÆ% ¸Æ8ÔLÊÆ ÓÆ ÔÆ ñÆ7»è$ÕÆ$ ÙÆ ÛÆ8•Ï4ÜÆ âÆ ãÆ ðÆ7û$äÆ$ èÆ8Ø÷4êÆ% òÆ8ÔL„Ç Ç ŽÇ ²Ç7»è$Ç$ “Ç •Ç8•Ï4–Ç œÇ Ç ±Ç7û$žÇ$ ¢Ç8Ø÷4¤Ç ªÇ8¬$«Ç ¯Ç °Ç% ³Ç8 ÞÈ8_check_stuff_is_send_syncÁÌáÈ úÈ ûÈ ýÈ ÎÍ48É8Ø÷4“É šÉ8¡ÐœÉ'žÉ8ç.d É ¬É ¯É7»è­É% °É8ÂÉ8movedÁ,ÆÉ ÌÉ8¡ÐÎÉ'ÐÉ8ç.dÒÉ ÞÉ áÉ7»èßÉ% âÉ8ôÉ8
shared_refÁTøÉ ƒÊ …Ê8Ø÷4†Ê% ŒÊ8žÊ8Ìš,¢Ê ¨Ê8Ø÷4ªÊ °Ê8¬$±Ê µÊ ¶Ê% ·Ê8ÉÊ8 lease_refÁLÍÊ ×Ê ÙÊ8Ìš,ÚÊ% ßÊ8ñÊ8Ìš,õÊ ûÊ8Ø÷4ýÊ ƒË8¬$„Ë ˆË ‰Ë% ŠË8Š4œË'¢Ë8ˆÙ,¤Ë ©Ë ¥Í ªË8¾ «Ë ¬Ë ®Ë ¤Í8¾ ÄË ÅË8»Ú,ÆË ËË ‘Í8$ÌË ÑË8 ÒË ÓË ÕË Í8ïË8 óË õË8Ìš,÷Ë% üË8–Ì8 šÌ œÌ8ñØLžÌ% §Ì8ÁÌ8 ÅÌ ÇÌ8Ó×TÉÌ% ÓÌ8íÌ8 ñÌ óÌ8éÖ,õÌ% úÌ% ’Í ·Í8¢4¸Í ¾Í ¿Í% ÀÍ<R We have a callback in RCU. Check what happens if we access the value from within.ÁüÝÍU+ ¿Î ÀÎ ÅÎ8$ÁÎ8 ÓÎ8 recursiveÁLÖÎ ßÎ àÎ âÎ ØÑ8ôÎ8Ø÷4øÎ ÿÎ8¼.<Ï'ˆÏ8÷$ŠÏ ŽÏ šÏ8KÏ'’Ï8æ ”Ï —Ï ™Ï7ˆ ˜Ï% ›Ï8Ø÷4®Ï ´Ï8‚.µÏ ¸Ï ÑÐ ¹Ï8´ ºÏ »Ï ½Ï ÐÐ
8ÓÏ
ÖÏ
×Ï8´ ØÏ ÚÏ7ÂÏÜÏ ßÏ ¦Ð8Ø÷4ùÏ ÿÏ8‚.€Ð ƒÐ Ð „Ð8´ …Ð †Ð
ˆÐ
‰Ð8´ ŠÐ ŒÐ7 ŽÐ% Ð
¼Ð
½Ð8´ ¾Ð% ÒÐ8ÔLäÐ íÐ îÐ ‚Ñ7ÂÏïÐ$ ñÐ
óÐ
ôÐ8Ø÷4õÐ ûÐ8¬$üÐ €Ñ Ñ% ƒÑ8ÔL•Ñ žÑ ŸÑ ÉÑ7Š  Ñ$ ¡Ñ8K£Ñ'¦Ñ8šäd¨Ñ ´Ñ ÈÑ µÑ8Ø÷4¶Ñ ¼Ñ8Å-L½Ñ ÆÑ ÇÑ% ÊÑ<A A panic from within the rcu callback should not change anything.ÁüçÑD+ ¸Ò ¹Ò ¾Ò8$ºÒ+ ÌÒ ÍÒ ýÒ8âÎÒ ÑÒ üÒ8
ÒÒ ÕÒ ûÒ8»<ÖÒ ÞÒ7ºÜàÒ8 ‹Ó8 rcu_panicÁLŽÓ —Ó ˜Ó šÓ °Õ8#¬Ó8À°Ó'³Ó8Á
,µÓ% ºÓ8ÌÓ8Ø÷4ÐÓ ×Ó8¼.<ÙÓ'àÓ8÷$âÓ æÓ òÓ8KçÓ'êÓ8æ ìÓ ïÓ ñÓ7ˆ ðÓ% óÓ8Ó4…Ô ‹Ô ŒÔ ÓÔ8Á
,Ô'’Ô8Ûd”Ô  Ô ÉÔ¡Ô8Ø÷4¤Ô ªÔ8‚.«Ô ®Ô ÈÔ ¯Ô8 °Ô ±Ô(³Ô8¬,¶Ô ¼Ô ÇÔ8Á
,¾Ô ÃÔ ÄÔ ÅÔ ÊÔ8is_errÁ4ËÔ ÑÔ ÒÔ% ÔÔ8ÔLæÔ ïÔ ðÔ ¡Õ7 ñÔ$ òÔ8KôÔ'÷Ô8šädùÔ …Õ  Õ †Õ8Ø÷4‡Õ Õ8æ-$ŽÕ ’Õ ŸÕ8K“Õ'–Õ8æ ˜Õ ›Õ žÕ7»èœÕ% ¢Õ< Handling null/none valuesÁì¿Õ+ éÕ êÕ ïÕ8$ëÕ8 ýÕ8nullsÁ,€Ö …Ö †Ö ˆÖ ºÛH8šÖ8Ø÷4žÖ ¥Ö8ú.l§Ö'´Ö8÷$¶Ö ºÖ ÌÖ8Û$»Ö ¿Ö ËÖ8KÀÖ'ÃÖ8æ ÅÖ ÈÖ ÊÖ7ˆ ÉÖ% ÍÖ8ßÖ8origÁ$ãÖ èÖ8Ø÷4êÖ ðÖ8æ-$ñÖ õÖ úÖ8©$öÖ% ûÖ8ÔL× –× —× ¼×7 ˜×$ ™×8K›×'ž×8šäd × ¬× »× ­×8«ï$®× ²×8¢4³× ¹× º×% ½×8Ï×8
$Ó× Ø×8Ø÷4Ú× à×8¬$á× å× æ×% ç×8Ó4ù× ÿ× €Ø Ø8
$Ø …Ø8ˆ—<†Ø Ø ŽØ% Ø8¢Ø8¬ ¦Ø ¨Ø8KªØ'­Ø8æ ¯Ø ²Ø µØ7»è³Ø% ¶Ø8ÈØ8«ï$ÌØ ÑØ8Ø÷4ÓØ ÙØ8ù%„ÚØ êØ ŒÙ8µ ëØ'îØ8
$ðØ ôØ õØ$ öØ8Û$øØ üØ ‹Ù8KýØ'€Ù8ƒ,‚Ù ‡Ù ŠÙ ˆÙ8¬ ‰Ù% Ù8Ó4ŸÙ ¥Ù ¦Ù µÙ8«ï$§Ù «Ù8ˆ—<¬Ù ³Ù ´Ù% ¶Ù8ÔLÈÙ ÑÙ ÒÙ ëÙ7Š ÓÙ$ ÔÙ8KÖÙ'ÙÙ8šädÛÙ çÙ êÙ èÙ8¬ éÙ% ìÙ8þÙ8«ï$‚Ú ‡Ú8° ,‰Ú'ŽÚ8´$TÚ šÚ ÉÚ8Ø÷4›Ú ¡Ú8ù%„¢Ú ²Ú ÈÚ
 ³Ú8©$´Ú'¸Ú ºÚ8K»Ú ¾Ú8 ¿ÚÀÚ$ ÂÚ8©$ÄÚ% ÊÚ8ÔLÜÚ åÚ æÚ ÿÚ7 çÚ$ èÚ8KêÚ'íÚ8šädïÚ ûÚ þÚ üÚ8¬ ýÚ% €Û8Ó4’Û ˜Û ™Û «Û8–+4šÛ  Û ªÛ ¡Û8¬ ¢Û$ £Û ¥Û8«ï$¦Û% ¬Û+ ÉÛ ÊÛ ÏÛ8$ËÛ< Multiple RCUs interacting.ÁôÝÛ8 ˆÜ8‚.‹Ü ŽÜ Ü ‘Ü àà"8,£Ü8ÏT©Ü& ³Ü8¬,µÜ »Ü7òü½Ü% ¿Ü8,ÑÜ8THREADSÁ<×Ü& ÞÜ8¬,àÜ æÜ7ÂÏèÜ% êÜ8üÜ8Ø÷4€Ý ‡Ý8¼.<‰Ý'Ý8÷$’Ý –Ý ¢Ý8K—Ý'šÝ8æ œÝ ŸÝ ¡Ý7ˆ  Ý% £Ý8Š4µÝ'»Ý8ˆÙ,½Ý ÂÝ ôß ÃÝ8ˆÙ,ÄÝ ÉÝ ËÝ óß8
áÝ8 åÝ8çÝ7ˆ êÝ!ëÝ8Âü<íÝ õÝ áß8ˆÙ,Þ ”Þ8»Ú,•Þ šÞ Êß ›Þ8 œÞ Þ ŸÞ Éß8
½Þ8 ÁÞ8ÃÞ7ˆ ÆÞ!ÇÞ8ÏTÉÞ ÔÞ ¯ß8Ø÷4öÞ üÞ8‚.ýÞ €ß ß ß8ÔÚ‚ß …ß
‡ß
ˆß8ÔÚ‰ß ß7 ß% ‘ß% Ëß †à8¢4‡à à Žà% à8ÔL¡à ªà «à Ñà
8Âü<¬à
´à8ÏT¶à$ Àà
Âà
Ãà8Ø÷4Äà Êà8¬$Ëà Ïà Ðà% Òà+ ïà ðà õà8$ñà<F Make sure the reference count and compare_and_swap works as expected.ÁüƒáI8 Ùá8 cas_ref_cntÁ\Üá çá èá êá æô4+ üá ýá ‡â8âþá â †â8µ $‚â8,™â8ÏTŸâ& ©â8¬,«â ±â7Âϳâ% µâ+ Çâ Èâ ×â8âÉâ Ìâ Öâ8
Íâ Ðâ Õâ8µ $Ñâ8,éâ8ÏTïâ& ùâ8¬,ûâ ã7òüƒã% …ã8—ã8Ø÷4›ã ¢ã8¼.<¤ã'«ã8÷$­ã ±ã ½ã8K²ã'µã8æ ·ã ºã ¼ã7ˆ »ã% ¾ã8
Ðã8´ Ôã8Öã7ˆ Ùã!Úã8ÏTÜã çã Óòr8ýã8«ï$ä †ä8Ø÷4ˆä Žä8Å-Lä ˜ä ™ä% šä8ÔL°ä ¹ä ºä Ãä8´ »ä$ ¼ä
¾ä8«ï$¿ä% Ää8Úä8´ Ýä ßä7Š áäãä7 æä èä ÷å8ÔLºå Ãå Äå àå7Š Åå$ Æå8KÈå'Ëå8šädÍå Ùå ßå Úå8«ï$Ûå% áå8æ8n1Á‘æ ”æ8K–æ'™æ8æ ›æ žæ ¤æ8´ Ÿæ ¡æ7 £æ% ¥æ8îæ8fillupÁ4òæ ùæûæ þæ õè 8˜ç8´ ›ç ç7Š Ÿç¡ç7ˆ ¤ç ¦ç è8Û$Äç Èç ƒè
 Éç ×ç7ˆ Êç!Ëç8ÏTÍç Øç8ØÙç Üç îç Ýç8 Þç ßç8Ø÷4áç çç8¬$èç ìç íç ïç8collectÁ<ðç'÷ç ùç8öúç ýç8 þçÿç è ‚è8$Ÿè ¤è ßè8©$Âè% öè8Œé8guardsÁ4é —é8 4™é Ÿé  é% ¡é8Öé8prevÁ$Úé ßé8Ø÷4áé çé8ù%„èé øé ê ùé8«ï$úé$ þé8K€ê'ƒê8ƒ,…ê Šê Žê ‹ê8•Œ Œê% ê8Ó4¦ê ¬ê ­ê Âê8–+4®ê ´ê Áê µê8«ï$¶ê$ ºê ¼ê8«‘ $½ê% Ãê8ã$Ùê Ýê äê8â 4Þê% åê8ÔL­ë ¶ë ·ë Óë7Š ¸ë$ ¹ë8K»ë'¾ë8šädÀë Ìë Òë Íë8«ï$Îë% Ôë8ÔLœì ¥ì ¦ì Àì7Š §ì$ ¨ì8Kªì'­ì8šäd¯ì »ì ¿ì ¼ì8•Œ ½ì% Áì8ÔL×ì àì áì øì
8´ âì äì7 æì$ çì
éì
êì8Ø÷4ëì ñì8¬$òì öì ÷ì% ùì8í8n2Á“í –í8K˜í'›í8æ í  í ¢í8´ ¡í% £í8ã$¹í ½í Âí8«‘ $¾í% Ãí8Ùí8â 4Ýí äí8 4æí ìí íí% îí8£î8«‘ $§î ¬î8° ,®î'³î8´$Tµî ¿î ïî8Ø÷4Àî Æî8ù%„Çî ×î îî Øî8«ï$Ùî$ Ýî8Kßî'âî8ƒ,äî éî íî êî8ª— ëî% ðî8ã$†ï Šï ‘ï8â 4‹ï% ’ï8Ó4¨ï ®ï ¯ï Âï8–+4°ï ¶ï Áï ·ï8•Œ ¸ï$ ºï ¼ï8«‘ $½ï% Ãï8ÔLýï †ð ‡ð £ð7 ˆð$ ‰ð8K‹ð'Žð8šädð œð ¢ð ð8«ï$žð% ¤ð8ÔLúð ƒñ „ñ žñ7 …ñ$ †ñ8Kˆñ'‹ñ8šädñ ™ñ ñ šñ8•Œ ›ñ% Ÿñ8ÔLäñ íñ îñ ˆò7 ïñ$ ðñ8Kòñ'õñ8šäd÷ñ ƒò ‡ò „ò8ª— …ò% ‰ò8ÔLŸò ¨ò ©ò Àò
8´ ªò ¬ò7 ®ò$ ¯ò
±ò
²ò8Ø÷4³ò ¹ò8¬$ºò ¾ò ¿ò% Áò8æò8¬ êò ìò8Ø÷4îò ôò8Å-Lõò þò ÿò% €ó8ÔLÂó Ëó Ìó åó7Š Íó$ Îó8KÐó'Óó8šädÕó áó äó âó8¬ ãó% æó8ã$øó üó ƒô8Ø÷4ýó% „ô8ÔL´ô ½ô ¾ô ×ô7 ¿ô$ Àô8KÂô'Åô8šädÇô Óô Öô Ôô8¬ Õô% Øô% ÷ô”É,ù=þ74­*\Á*¥¿¤ÀÀ¿‹ß Í*ˆæ Ø*˜æ4Ð*§æ\Û*‚FPzèýu¾Áõ]‚Fþ7uõ]‚F½½
¾ÄDòEƒˆ\è*½½õ](Ÿ*&¥Ã¤ÄÃÄ‹ßèˆæ樦Í*˜æí¿còEØ*§æû‚FÅÀcÅ#&*-Ž ‚F  c cˆ¢cµ
 `£cÒ¦ `àB¤GS
ù§ÂŸ*Â
ÅÄDòE9±@üÉF4¢FDÔF˜ÇȥɣÊÈÊÉÇ¥ ÝFÍ àFöŽ ãF æF¡Kæ:óFŸ‰`ËÌÍ9;>@CEHJDïF,ïFÆÆäKlýFTýFÆÆêKìGGÆÆ³oFu\»Ÿƒ ƒðK ƒöK ´F'˜ÏХѣÒÑÏÒÐ¥UÍTöŽSRŠ äKÝFŠ êKàFŠ ðKãFŠ öKæF¡K°³·º¾ÁÅÈ(ºF(˜ÔÕ¥Ö£×ÕÔÖ×¥?Í>öŽ=<ØäKÝFÑšàFØðKãFØöKæF¡KØÙØž¡¥¨¬¯³îð ¡K¡KÓºFÓ
ØäKêKðKöKI(ÁF)˜ÚۥܣÝÚÜÝۥ͊öŽˆ¿cäKÝF¿cêKàF¿cðKãF¿cöKæF¡KÞÀcÞñôøûÿ õ÷ ¡K  c cˆ¢cµ
 `£cÒ¦ `àB¤GS
ù§ÙÁFÙ
ÞäKêKðKöK¨±¯¼ÊJüúH?< An adaptor to provide access to a part of larger structure.ÁºIúü¾I`] This is the *active* part of this module. Use the [module documentation](index.html) for theÁdŸJ details.ÁÕJà¥áâàáâØ‘ ÙJ¤Ø ÜJð‘ ßJ¡L±ìi0Â% ãäå1368;=LèJ4èJßßäLl÷JT÷JßßíLÔŠKŠKßß³oFu\»ŸØD µJ*ç¥èéèç騑¤Øð‘Š äLÙJŠ ØDÜJŠ íLßJ¡LZ]adhk(»J+ë¥ìíëìíØ‘Ë¤ØÊð‘ÉØäLÙJØØDÜJÚ˜ßJ¡LîÙî!$¹»ˆ ˆ¡L¡Lê»Jê
îäLØDíL(ÂJ,ð¥ñòòñðؑޤØÝð‘Ü¿cäLÙJ¿cØDÜJ¿cíLßJ¡LóÀcó-047;>ÀŠ ¡L Š c cˆ¢cµ
 `£cÒ¦ `àB¤GS
ù§ïÂJï
óäLØDíLo±vm94çTl¿U¥öö‹ß ÍUãMp²1=ÃHõ÷ÄDãMm9MÄDãMôô
õÄDeg ÐUôôÄD ùT-¥ùù‹ß°Š ÄDÍUãMÅÇ(ÿT.¥ûû‹ßøÓžÍUãMüÙüNPŒ ŒãMãMúÿTú
üÄD(†U/¥þþ‹ß¨¦ÍUãMÿÀcÿ±´OQŽ ãM Ž c cˆ¢cµ
 `£cÒ¦ `àB¤GS
ù§ý†Uý
ÿÄDö±üU0¥‹ßÄDÍUãM‚¹V\q ãM™jU
ÄD¾H‘U1¥‹ßUãM[^;?1¥‹ßµßÄDÄDÍUãM‡·ß³ ãM ãM‘U
ÄDò¹
ø œU2¥‹ßOºÄD ÍUãMŠ»ŠpsVX ãM ãM¿ßÀßÁßLessÁÂßÃßÄß~Å߯ßÇßGreaterÁÈßåºÝÈnûê7ˆ œUˆ
ŠÄD¹
P!¡U3¥ŒŒ‹ßoíßÄDÄD!ÍUãMïߘ[] ãM ãMÛ¼ݼÞ¼©ß¼à¼ÛἈcSñŸ«‡zÙÈ !¡U
ÄD¹
 "­U4¥‹ßzšeÄD"ÍUãMežVX˜ ãM ˜ù™jŽù"­UŽÍì¶Ì Ë¢e¶Ì Ù
ÄD¶Ì êºðòô¼9ÔÄV Access to an constant.ÁßVúüãV^[ This wraps a constant value to provide [`Access`] to it. It is constant in the sense that,ÁüÂW]Z unlike [`ArcSwapAny`] and [`Map`], the loaded value will always stay the same (there's noÁ¤ X remote `store`).ÁµXúü¹X`] The purpose is mostly testing and plugging a parameter that works generically from code thatÁüšY,) doesn't need the updating functionality.ÁDZ¥‹ß ŸZOìXN#£¤¬ÄDO¼9MÄDO
ÄDdf,¢ZÄD #ÐY5¥‹ß®„À #ŸZO¼¾($ÖY6¥‹ßïÓž$ŸZÙš NP OO˜$ÖY˜
šÄD(%ÝY7¥œœ‹ßލ¦%ŸZOÀc¨«OQšœ šO  c cˆ¢cµ
 `£cÒ¦ `àB¤GS
œù§%ÝY
ÄDö±ü&äY8¥ŸŸ‹ßŒêà &ŸZ ¦©OUj O™jž&äYž
 ÄD·H'èY9¥¢¢‹ßEOKN;?9¥¤¤‹ß}âÅ 'ŸZ·ß¥˜ˆŠžŸ žO ŸO£'èY£
¥ÄDç¹
í(óY:¥§§‹ß4¤Ç (ŸZ»¨NQOQ ¡  O ¡OÈ ¦(óY¦
¨ÄD°¹