using concurrentusing afConcurrent** (Service) -** Use to create 'LocalRef' instances whose contents can be *cleaned* up. Erm, I mean deleted! ** ** This is particularly important in the context of web applications where resources need to be ** *cleaned* up at the end of a web request / thread. ** ** 'LocalRef' instances may also be injected directed into your classes:** ** pre>** const class Example {** @Inject const LocalMap localMap** ** new make(|This|in) { in(this) }** }** <pre** ** Then when 'cleanUpThread()' is called, all thread local data created by this manager will be** deleted from 'Actor.locals' ** ** @since 1.6.0constmixin ThreadLocalManager {** Creates a `LocalRef` with the given default function.abstract LocalRef createRef(Str name, |->Obj?|? defFunc := null)** Creates a `LocalList` with the given name.abstract LocalList createList(Str name)** Creates a `LocalMap` with the given name.abstract LocalMap createMap(Str name)** Returns all (fully qualified) keys in the current thread associated / used with this manager. abstract Str[] keys()** Add a handler to be called on thread clean up. Handlers need to be added for each thread.abstract Void addCleanUpHandler(|->| handler)** Removes all values in the current thread associated / used with this manager.abstract Void cleanUpThread()}internalconstclass ThreadLocalManagerImpl : ThreadLocalManager {staticprivateconst AtomicInt counter := AtomicInt(0)privateconst LocalList cleanUpHandlersconst Str prefixnew make(){this.prefix = createPrefixthis.cleanUpHandlers = createList("ThreadLocalManager.cleanupHandlers")}override LocalRef createRef(Str name, |->Obj?|? defFunc := null){ LocalRef("${prefix}.\${id}.${name}", defFunc)}override LocalList createList(Str name){ LocalList("${prefix}.\${id}.${name}")}override LocalMap createMap(Str name){ LocalMap("${prefix}.\${id}.${name}")}override Str[] keys(){ Actor.locals.keys .findAll {it.startsWith(prefix)} .sort}override Void addCleanUpHandler(|->| handler){ cleanUpHandlers.add(handler)}override Void cleanUpThread(){ cleanUpHandlers.each | |->| handler| { handler.call } keys.each { Actor.locals.remove(it)}}// ---- Helper Methods ------------------------------------------------------------------------private Str createPrefix(){ count := counter.incrementAndGet padded := count.toStr.padl(2, '0') prefix := "TLM-${padded}"return prefix}}