using concurrent** Manages an Obj reference stored in 'Actor.locals' with a unique key.@Jsconstclass LocalRef {staticprivateconst AtomicInt counter := AtomicInt(0)privateconst |->Obj?|? defFunc** The qualified name this 'ThreadLocal' is stored under in 'Actor.locals'. ** 'qname' is calculated from 'name'.const Str qname** The variable name given to the ctor.const Str name** The object held in 'Actor.locals'. If a value is not mapped when read, 'initFunc()' is ** called to create a default object. Obj? val { get {// don't set a local var if it's null!if(!isMapped && defFunc != null) Actor.locals[qname] = defFunc.callreturn Actor.locals[qname]} set { Actor.locals[qname] = it}}** Creates a 'LocalRef' with given name.** ** If not null, 'defFunc' is called to create a default object whenever 'val' is read and a ** value is not mapped in 'Actor.locals'. This object is then stored and returned. ** This allows the creation of non-const default objects in multiple threads.** ** 'initFunc' must be immutable. new makeWithFunc(Str name, |->Obj?|? defFunc := null){this.qname = createPrefix(name, 4)this.name = namethis.defFunc = defFunc}** Returns 'true' if 'Actor.locals' holds an entry for this 'qname'. Bool isMapped(){ Actor.locals.containsKey(qname)}** Removes this object from 'Actor.locals'. Void cleanUp(){ Actor.locals[qname] = null Actor.locals.remove(qname)}// ---- Helper Methods ------------------------------------------------------------------------private Str createPrefix(Str name, Int pad){ count := counter.incrementAndGet padded := ConcurrentBase64.toBase64(count, pad) inter := name.contains("\${id}") ? name : "\${id}.${name}" prefix := inter.replace("\${id}", padded)return prefix}** Returns a string representation the referenced value.override Str toStr(){ val?.toStr ?: "null"}}