The Shared-Immutable Pattern

Why immutability underpins performance, safety, and parallelism in Solidean.

Most data types in Solidean are shared-immutable:
they are built once and can then be shared freely without risk of races or hidden side effects.
This pattern provides both performance and safety: a foundation for exact, parallel geometry processing.

How it works

  • Initialization phase:
    At a low level, a shared-immutable object is first created in an uninitialized state.
    An Operation can then define its content exactly once.
    That content becomes atomically available sometime before the operation finishes (Context::execute).

  • No mutation:
    Once populated, the object cannot change. You can read from it, share it between threads, and pass it into later operations, but never modify it.

  • Lifetime model:
    While immutability governs the content, objects still follow a clear lifetime:
    they remain valid until explicitly released (or until their Lifetime expires, e.g. UntilIndirectRelease).

Which objects are shared-immutable?

  • TypedBlob: output data, immutable once filled.
  • Surface: user-provided geometry, fixed after creation.
  • Mesh: a set of surfaces plus flags, fixed once constructed.
  • ExactArithmetic: fixed precision and extent; must be recreated for a different bound.

Operations themselves are slightly different: they act like builders.
They allow recording sub-operations, but remain append-only. Older data is never modified, and operations cannot be reused after execution.

Why immutability improves performance

It is a common intuition that mutability = performance.
In highly parallel systems, the opposite is true:

  • No synchronization needed: immutable objects can be shared across many threads without locks.
  • No hidden invalidation: nothing changes "behind your back," so caches and references remain valid.
  • Zero-copy reuse: since results cannot be mutated, they can safely be referenced in new objects.

A powerful example: meshes

Internally, a Mesh is not a monolithic block but a collection of small shared-immutable surflets.
When you run a Boolean operation:

  • Only interacting ("cutting") surflets are newly created.
  • All unaffected surflets are simply referenced into the new mesh, zero-copy.

This enables:

  • Iterated Booleans: each step only recomputes what changes.
  • Branching workflows: you can compute multiple results from the same workpiece without duplicating data.

By contrast, a mutable accumulator or voxel grid approach cannot support this kind of reuse.