/* Ċ Ġ* Ġ( c ) ĠCopyright Ġ 2 0 1 9 ĠGl ade ĠDiv ine y . Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġio . gl aded . watch able . store Ċ Ċ import Ġio . gl aded . watch able . util . guard Ċ import Ġkotlinx . coroutines . Coroutine Scope Ċ import Ġkotlinx . coroutines . Deferred Ċ import Ġkotlinx . coroutines . Job Ċ import Ġkotlinx . coroutines . Supervisor Job Ċ import Ġkotlinx . coroutines . async Ċ import Ġjava . lang . ref . Weak Reference Ċ import Ġkotlin . coroutines . Coroutine Context Ċ Ċ /** ĠA ĠRAM Ġcache Ġthat Ġprevents Ġover use Ġof Ġbacking Ġstore Ġby Ġserving Ġobjects Ġit Ġalready Ġhas Ġloaded . Ġ*/ Ċ class ĠCache < T Ġ: ĠAny >( ĊĠĠĠ Ġcontext : ĠCor outine Context , ĊĠĠĠ Ġprivate Ġval Ġback : ĠStore < T > Ċ ) Ġ: ĠStore < T >, ĠCor outine Scope Ġ{ ĊĠĠĠ Ġoverride Ġval Ġcoroutine Context Ġ= Ġcontext Ġ+ ĠJob () ĊĊĠĠĠ Ġprivate Ġval Ġfinding Ġ= Ġmutable Map Of < String , ĠDeferred < T >> (). guard () ĊĠĠĠ Ġprivate Ġval Ġfound Ġ= Ġmutable Map Of < String , ĠWeak Reference < T >> (). guard () ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġget ( key : ĠString ): ĠT Ġ= ĊĠĠĠĠĠĠĠ Ġfound Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclear Dead () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget ( key )?. get () ĊĠĠĠĠĠĠĠ Ġ} Ġ?: Ġfinding Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIf Ġa Ġprior Ġentry Ġalready Ġfailed Ġgo Ġahead Ġand Ġtry Ġagain . ĊĠĠĠĠĠĠĠĠĠĠĠ Ġentries . remove If Ġ{ Ġit . value . is Cancelled Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart Getting ( key ) ĊĠĠĠĠĠĠĠ Ġ}. await () ĊĊĠĠĠ Ġprivate Ġfun ĠMutable Map < String , ĠDeferred < T >> . start Getting ( key : ĠString ): ĠDeferred < T > Ġ= ĊĠĠĠĠĠĠĠ Ġget Or Put ( key ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠDo Ġthis Ġasynchronously , Ġbut Ġdo Ġnot Ġallow Ġits Ġfailure Ġto Ġbring Ġdown Ġ[ Cache ] Ġcontext ĊĠĠĠĠĠĠĠĠĠĠĠ Ġasync ( coroutine Context Ġ+ ĠSuper visor Job ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġback . get ( key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( qu ash Find ( key )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠOnly Ġrecord Ġthe Ġresult Ġif Ġwe Ġqu ashed Ġthe Ġfind ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfound Ġ{ Ġput ( key , ĠWeak Reference ( result )) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġput ( key : ĠString , Ġvalue : ĠT ) Ġ{ ĊĠĠĠĠĠĠĠ Ġqu ash Find ( key ) Ġ// ĠOut standing Ġgets Ġshould Ġnot Ġupdate Ġcache ĊĠĠĠĠĠĠĠ Ġfound Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġclear Dead () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġput ( key , ĠWeak Reference ( value )) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġback . put ( key , Ġvalue ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĠE limin ate Ġunused Ġrefs . Ġ*/ ĊĠĠĠ Ġprivate Ġfun ĠMutable Map < String , ĠWeak Reference < T >> . clear Dead () Ġ{ ĊĠĠĠĠĠĠĠ Ġentries . remove If Ġ{ Ġit . value . get () Ġ== Ġnull Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġremove ( key : ĠString ) Ġ{ ĊĠĠĠĠĠĠĠ Ġqu ash Find ( key ) Ġ// ĠOut standing Ġgets Ġshould Ġnot Ġupdate Ġcache ĊĠĠĠĠĠĠĠ Ġfound Ġ{ Ġremove ( key ) Ġ} ĊĠĠĠĠĠĠĠ Ġback . remove ( key ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġqu ash Find ( key : ĠString ): ĠBoolean Ġ= ĊĠĠĠĠĠĠĠ Ġfinding Ġ{ Ġremove ( key ) Ġ} Ġ!= Ġnull ĊĊĠĠĠ Ġoverride Ġfun Ġkeys () Ġ= Ġback . keys () Ċ } Ċ