Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Atomics

Shared state (optional; prefer pipes)

The preferred method of ITC is via pipes (“share by communicating”).

However, thread-safe variables and collections can have their use, so Final provides a curated collection of thread-safe constructs.

AtomicInt

A single thread-safe integer. Readonly .value; mutating methods return the new value except .set^ / .zero^.

KindNameEffectDescription
classnew( -- a:AtomicInt )starts at 0
propvalueIntcurrent value (const)
methodinc( -- n:i )add 1; return new value
methoddec( -- n:i )subtract 1; return new value
methodadd( n:i -- n':i )add n; return new value
methodsub( n:i -- n':i )subtract n; return new value
methodset( n:i -- )store n
methodzero( -- )store 0
AtomicInt.new^ >ts
t:.inc^ $ nl          // 1
10 t:.add^ $ nl        // 11
t:.value@ $ nl        // 11
t:drop

Prefer a Pipe when you are passing work between Pips. Use AtomicInt when several Pips only need to bump a counter.

AtomicList / AtomicStringList

These are mutex-guarded Lists for reading/writing an item.

Iteration via foreach uses a snapshot clone, so is threadsafe. NOTE: do NOT iterate AtomicLists with a range-based iterator or other counted loop; iteration is not threadsafe using that approach.

AtomicDynamicObject

A mutex-guarded DynamicObject (string keys) that is threadsafe for reading a key, writing a key value, and adding a new field. foreach uses a snapshot clone, similar to the AtomicLists.

Average and MovingAverage

Average is a type used for accumulating an exactly correct mean and variance for data samples added via the add method, without retaining the samples. MovingAverage is used for calculating a recent, moving average. Both are threadsafe for add, and the atomic read methods.

See help Average and help MovingAverage for the apis.

See Counter / Average / MovingAverage

atomicVar:

A mutex guarded var, threadsafe for fetch and set (@ / !).

Not that const: is inherently threadsafe, as long as the definition precedes any use.

Note that both atomicVar: and const: write to the dictionary, so are disallowed when Pips are running. And both run in interpret/immediate mode, so can not even be invoked by Pips.

General Caveats

In all the collections above, threadsafety extends only to the operations listed. In particular, the threadsafety of any objects stored in these containers have the threadsafety of the object itself, which for most Objects is NOT threadsafe.

Threadsafe Operations

  • reading any class-level sealed readonly/const property; eg Math.pi
  • reading properties from object instances that are not mutated over the lifetime of the reading Pips
  • creating/mutating objects created by a Pip, and not shared
  • reading/mutating an object created by a Pip, then sent via a Pipe to another Pip, under contract that the sending Pip then no longer mutates or uses the object; eg. preparing a DynamicObject by Pip1, then sending it to Pip2, abandoning its ownership
  • calling object factories, such as opening new file streams
  • writing to the shared stdout/stderr, eg using $/$$