using concurrent::Actor** A wrapper around [Actor.locals]`concurrent::Actor.locals` ensuring a unique namespace per ** instance. this means you don't have to worry about name clashes. ** ** Example usage:** ** pre>** stash1 := ThreadStash("prefix")** stash1["wot"] = "ever"** ** stash2 := ThreadStash("prefix")** stash2["wot"] = "banana"** ** Obj.echo(stash1["wot"]) // --> ever** <pre** ** Though typically you would create calculated field wrappers:** ** pre>** const class Example** private const ThreadStash stash := LocalStash(typeof.name)** ** MyService wotever {** get { stash["wotever"] }** set { stash["wotever"] = it }** }** }** <pre**** @since 1.3.0 (a replacement for 'LocalStash')constclass ThreadStash {** The prefix used to identify all keys used with this stashconst Str prefixprivate Int? counter { get { Actor.locals["${typeof.qname}.counter"]} set { Actor.locals["${typeof.qname}.counter"] = it}}** A thread-local count is added to the given prefix to make it truly unique.new make(Str prefix){this.prefix = createPrefix(prefix)}** Get the value for the specified name. @Operator Obj? get(Str name, |->Obj|? defFunc := null){ val := Actor.locals[key(name)]if(val == null){if(defFunc != null){ val = defFunc.call set(name, val)}}return val}** Set the value for the specified name. If the name was already mapped, this overwrites the old ** value. @Operator Void set(Str name, Obj? value){ Actor.locals[key(name)] = value}** Returns all (fully qualified) keys associated / used with this stash. Note the returns Str[] keys(){ Actor.locals.keys .findAll {it.startsWith(prefix)} .sort}** Returns 'true' if this stash contains the given name** ** @since 1.3.2 Bool contains(Str name){ keys.contains(key(name))}** Remove the name/value pair from the stash and returns the value that was. If the name was ** not mapped then return null. Obj? remove(Str name){ Actor.locals.remove(key(name))}** Removes all key/value pairs from this stash Void clear(){ keys.each { Actor.locals.remove(it)}}// ---- Helper Methods ------------------------------------------------------------------------private Str createPrefix(Str strPrefix){ count := counter ?: 1 padded := count.toStr.padl(4, '0') prefix := "${strPrefix}.${padded}." counter = count + 1return prefix}private Str key(Str name){return"${prefix}${name}"}}