using concurrent::AtomicRef** A List that provides fast reads and lightweight writes between threads using the copy on write paradigm.**** The list is stored in an [AtomicRef]`concurrent::AtomicRef` through which all reads are made. ** Writing makes a 'rw' copy of the list and is thus a more expensive operation.** ** > **CAUTION:** ** Write operations ( 'add', 'remove' & 'clear' ) are not synchronised. ** This makes them lightweight but also susceptible to **data-loss** during race conditions.** Though this may be acceptable for *caching* situations where values are re-calculated on demand.** ** All values held in the list must be immutable.@Jsconstclass AtomicList {privateconst AtomicRef atomicList := AtomicRef()** Used to parameterize the backing list.** ** syntax: fantom** ** AtomicList() { it.valType = Str# }const Type valType := Obj?# @NoDoc // it's a boring ctor!new make(|This|? f := null){ f?.call(this)} @NoDoc @Deprecated { msg="Use 'val' instead"} Obj?[] list { get { val } set { val = it}}** Gets or sets a read-only copy of the backing map. Obj?[] val { get {if(atomicList.val == null) atomicList.val = valType.emptyListreturn atomicList.val } set { Utils.checkListType(it.typeof, valType) atomicList.val = it.toImmutable }}** Add the specified item to the end of the list.** Return this. @Operator This add(Obj? item){ Utils.checkType(item?.typeof, valType, "List value") rwList := val.rw rwList.add(item) val = rwListreturnthis}** Insert the item at the specified index.** A negative index may be used to access an index from the end of the list.** Size is incremented by 1.** Return this.** Throw IndexErr if index is out of range.** Throw ReadonlyErr if readonly. This insert(Int index, Obj? item){ Utils.checkType(item?.typeof, valType, "List value") rwList := val.rw rwList.insert(index, item) val = rwListreturnthis}** Removes the specified item from the list, returning the removed item.** If the item was not mapped then return 'null'. Obj? remove(Obj item){ rwList := val.rw oVal := rwList.remove(item) val = rwListreturn oVal }** Remove the object at the specified index. ** A negative index may be used to access an index from the end of the list. ** Return the item removed. Obj? removeAt(Int index){ rwList := val.rw oVal := rwList.removeAt(index) val = rwListreturn oVal }** Remove all key/value pairs from the map. Return this. This clear(){ val = val.rw.clearreturnthis} This push(Obj? item){ Utils.checkType(item?.typeof, valType, "List value") rwList := val.rw rwList.push(item) val = rwListreturnthis} Obj? pop(){ rwList := val.rw oVal := rwList.pop val = rwListreturn oVal} Obj? peek(){ val.peek}// ---- Common List Methods --------------------------------------------------------------------** Returns 'true' if this list contains the specified item. Bool contains(Obj? item){ val.contains(item)}** Call the specified function for every item in the list. Void each(|Obj? item, Int index| c){ val.each(c)}** Returns the item at the specified index.** A negative index may be used to access an index from the end of the list. @Operator Obj? get(Int index){ val[index]}** Return the item at index 0, or if empty return null. Obj? first(){ val.first}** Return the item at index-1, or if empty return null. Obj? last(){ val.last}** Return 'true' if size() == 0 Bool isEmpty(){ val.isEmpty}** Get a read-write, mutable List instance with the same contents. Obj?[] rw(){ val.rw}** Get the number of values in the map. Int size(){ val.size}** Returns a string representation the list.override Str toStr(){ val.toStr}}