No matching definitions.

arc

stdlib/arc.tur

Arc<T>, the thread-safe counterpart to rc<T>.

Arc is rc with atomic counts: several OS threads may clone and drop the same value without racing the refcount. That is the whole difference -- where rc<T> uses plain uint64_t counts and is single-threaded, Arc uses __atomic_* operations, so an Arc is what you reach for to share an immutable value across (async ...) bodies or spawned threads.

The runtime has always been here (src/runtime/arc.{c,h}); this module is the language surface over it. Before it existed, the only user in the tree -- tests/fixtures/arc-basic -- hand-rolled its own control block in inline C, with a layout that had already drifted from the real ArcControlBlock. See docs/archive/stdlib-arc-surface-missing.md.

Not autoloaded: (import arc :refer [arc-new arc-clone arc-get arc-drop]).

Unlike rc<T> there is **no cycle collector** for Arc. A cycle of strong Arcs leaks; break it with arc-downgrade / arc-upgrade.

(let [a (arc-new 42)
      b (arc-clone a)]
  (println (arc-get b))            ; => 42
  (println (arc-strong-count a))   ; => 2
  (arc-drop b)
  (arc-drop a))

Since: 2026-08-20

defn

arc-new

(arc-new [v :int] :Arc)

allocate an Arc holding an int payload, strong count 1.

vthe value to share

A new Arc with strong count 1 and the weak sentinel held.

(arc-get (arc-new 42))  ; => 42

Since: 2026-08-20

defn

arc-clone

(arc-clone [^borrow a :Arc] :Arc)

add a strong reference.

athe Arc to clone (borrowed; the caller keeps its own handle)

A second Arc onto the same value. Both must be dropped.

(let [a (arc-new 1) b (arc-clone a)]
  (println (arc-strong-count a)))  ; => 2

Since: 2026-08-20

defn

arc-get

(arc-get [^borrow a :Arc] :int)

read the shared value.

Borrows its handle, so reading does not consume the caller's Arc.

athe Arc to read (borrowed)

The contained value; 0 for a null handle or one already dropped.

(arc-get (arc-new 7))  ; => 7

Since: 2026-08-20

defn

arc-strong-count

(arc-strong-count [^borrow a :Arc] :int)

how many Arc handles share this value.

athe Arc to inspect (borrowed)

The current strong count; 0 for a null handle.

(arc-strong-count (arc-new 1))  ; => 1

Since: 2026-08-20

defn

arc-weak-count

(arc-weak-count [^borrow a :Arc] :int)

how many ArcWeak handles point at this value.

The runtime keeps a +1 sentinel in the weak count while any strong reference is alive, so that the control block itself is not freed out from under a live weak handle. This subtracts it, reporting the number of ArcWeak values a caller actually holds.

athe Arc to inspect (borrowed)

The weak count excluding the sentinel; 0 for a null handle.

(let [a (arc-new 1) w (arc-downgrade a)]
  (println (arc-weak-count a)))  ; => 1

Since: 2026-08-20

defn

arc-drop

(arc-drop [a :Arc] :void)

release one strong reference.

When the last strong reference goes, the value is dropped; the control block itself survives until the last weak handle goes too.

athe Arc to release (consumed -- do not use it afterwards)
(let [a (arc-new 1)] (arc-drop a))

Since: 2026-08-20

defn

arc-downgrade

(arc-downgrade [^borrow a :Arc] :ArcWeak)

make a non-owning ArcWeak from an Arc.

A weak handle does not keep the value alive, which is how an Arc cycle gets broken -- there is no cycle collector for Arc.

athe Arc to downgrade (borrowed)

An ArcWeak onto the same control block. Release it with arc-weak-drop.

(let [a (arc-new 1) w (arc-downgrade a)]
  (arc-weak-drop w) (arc-drop a))

Since: 2026-08-20

defn

arc-upgrade

(arc-upgrade [^borrow w :ArcWeak] :(Option Arc))
defn

arc-weak-drop

(arc-weak-drop [w :ArcWeak] :void)

release one weak reference.

Frees the control block when this was the last reference of either kind.

wthe ArcWeak to release (consumed -- do not use it afterwards)
(let [a (arc-new 1) w (arc-downgrade a)]
  (arc-weak-drop w) (arc-drop a))

Since: 2026-08-20

Internal definitions
Arc
ArcWeak
arc-try-upgrade-- try to get a strong Arc back from a weak handle.
arc-weak->arc-- internal: view a weak handle as the strong one it